Line data Source code
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 :
20 : #include <hintids.hxx>
21 : #include <vcl/outdev.hxx>
22 : #include <sfx2/printer.hxx>
23 : #include <editeng/eeitem.hxx>
24 : #include <editeng/flditem.hxx>
25 : #include <editeng/editeng.hxx>
26 : #include <svx/svdoutl.hxx>
27 : #include <editeng/colritem.hxx>
28 : #include <svx/svdpage.hxx>
29 : #include <svx/svdogrp.hxx>
30 : #include <editeng/langitem.hxx>
31 : #include <editeng/unolingu.hxx>
32 : #include <editeng/measfld.hxx>
33 : #include <svx/svdpool.hxx>
34 : #include <fmtanchr.hxx>
35 : #include <charatr.hxx>
36 : #include <frmfmt.hxx>
37 : #include <charfmt.hxx>
38 : #include <viewimp.hxx>
39 : #include <swhints.hxx>
40 : #include <doc.hxx>
41 : #include <IDocumentUndoRedo.hxx>
42 : #include <docsh.hxx>
43 : #include <rootfrm.hxx>
44 : #include <poolfmt.hxx>
45 : #include <viewsh.hxx>
46 : #include <drawdoc.hxx>
47 : #include <UndoDraw.hxx>
48 : #include <swundo.hxx>
49 : #include <dcontact.hxx>
50 : #include <dview.hxx>
51 : #include <mvsave.hxx>
52 : #include <flyfrm.hxx>
53 : #include <dflyobj.hxx>
54 : #include <svx/svdetc.hxx>
55 : #include <editeng/fhgtitem.hxx>
56 : #include <svx/svdpagv.hxx>
57 : #include <txtfrm.hxx>
58 : #include <editeng/frmdiritem.hxx>
59 : #include <fmtornt.hxx>
60 : #include <svx/svditer.hxx>
61 :
62 : #include <vector>
63 : #include <switerator.hxx>
64 :
65 : using namespace ::com::sun::star;
66 : using namespace ::com::sun::star::linguistic2;
67 :
68 : /** local method to determine positioning and alignment attributes for a drawing
69 : * object, which is newly connected to the layout.
70 : *
71 : * Used for a newly formed group object <SwDoc::GroupSelection(..)>
72 : * and the members of a destroyed group <SwDoc::UnGroupSelection(..)>
73 : */
74 0 : static void lcl_AdjustPositioningAttr( SwDrawFrmFmt* _pFrmFmt,
75 : const SdrObject& _rSdrObj )
76 : {
77 0 : const SwContact* pContact = GetUserCall( &_rSdrObj );
78 : OSL_ENSURE( pContact, "<lcl_AdjustPositioningAttr(..)> - missing contact object." );
79 :
80 : // determine position of new group object relative to its anchor frame position
81 0 : SwTwips nHoriRelPos = 0;
82 0 : SwTwips nVertRelPos = 0;
83 : {
84 0 : const SwFrm* pAnchorFrm = pContact->GetAnchoredObj( &_rSdrObj )->GetAnchorFrm();
85 : OSL_ENSURE( !pAnchorFrm ||
86 : !pAnchorFrm->IsTxtFrm() ||
87 : !static_cast<const SwTxtFrm*>(pAnchorFrm)->IsFollow(),
88 : "<lcl_AdjustPositioningAttr(..)> - anchor frame is a follow. Please inform OD." );
89 0 : bool bVert = false;
90 0 : bool bR2L = false;
91 : // #i45952# - use anchor position of anchor frame, if it exist.
92 0 : Point aAnchorPos;
93 0 : if ( pAnchorFrm )
94 : {
95 : // #i45952#
96 0 : aAnchorPos = pAnchorFrm->GetFrmAnchorPos( ::HasWrap( &_rSdrObj ) );
97 0 : bVert = pAnchorFrm->IsVertical();
98 0 : bR2L = pAnchorFrm->IsRightToLeft();
99 : }
100 : else
101 : {
102 : // #i45952#
103 0 : aAnchorPos = _rSdrObj.GetAnchorPos();
104 : // If no anchor frame exist - e.g. because no layout exists - the
105 : // default layout direction is taken.
106 : const SvxFrameDirectionItem* pDirItem =
107 0 : static_cast<const SvxFrameDirectionItem*>(&(_pFrmFmt->GetAttrSet().GetPool()->GetDefaultItem( RES_FRAMEDIR )));
108 0 : switch ( pDirItem->GetValue() )
109 : {
110 : case FRMDIR_VERT_TOP_LEFT:
111 : {
112 : // vertical from left-to-right - Badaa: supported now!
113 0 : bVert = true;
114 0 : bR2L = true;
115 : OSL_FAIL( "<lcl_AdjustPositioningAttr(..)> - vertical from left-to-right not supported." );
116 : }
117 0 : break;
118 : case FRMDIR_VERT_TOP_RIGHT:
119 : {
120 : // vertical from right-to-left
121 0 : bVert = true;
122 0 : bR2L = false;
123 : }
124 0 : break;
125 : case FRMDIR_HORI_RIGHT_TOP:
126 : {
127 : // horizontal from right-to-left
128 0 : bVert = false;
129 0 : bR2L = true;
130 : }
131 0 : break;
132 : case FRMDIR_HORI_LEFT_TOP:
133 : {
134 : // horizontal from left-to-right
135 0 : bVert = false;
136 0 : bR2L = false;
137 : }
138 0 : break;
139 : }
140 :
141 : }
142 : // use geometry of drawing object
143 0 : const SwRect aObjRect = _rSdrObj.GetSnapRect();
144 :
145 0 : if ( bVert )
146 : {
147 0 : if ( bR2L ) {
148 : //FRMDIR_VERT_TOP_LEFT
149 0 : nHoriRelPos = aObjRect.Left() - aAnchorPos.getX();
150 0 : nVertRelPos = aObjRect.Top() - aAnchorPos.getY();
151 : } else {
152 : //FRMDIR_VERT_TOP_RIGHT
153 0 : nHoriRelPos = aObjRect.Top() - aAnchorPos.getY();
154 0 : nVertRelPos = aAnchorPos.getX() - aObjRect.Right();
155 : }
156 : }
157 0 : else if ( bR2L )
158 : {
159 0 : nHoriRelPos = aAnchorPos.getX() - aObjRect.Right();
160 0 : nVertRelPos = aObjRect.Top() - aAnchorPos.getY();
161 : }
162 : else
163 : {
164 0 : nHoriRelPos = aObjRect.Left() - aAnchorPos.getX();
165 0 : nVertRelPos = aObjRect.Top() - aAnchorPos.getY();
166 : }
167 : //End of SCMS
168 : }
169 :
170 0 : _pFrmFmt->SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
171 0 : _pFrmFmt->SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
172 : // #i44334#, #i44681# - positioning attributes already set
173 0 : _pFrmFmt->PosAttrSet();
174 : // #i34750# - keep current object rectangle for drawing
175 : // objects. The object rectangle is used on events from the drawing layer
176 : // to adjust the positioning attributes - see <SwDrawContact::_Changed(..)>.
177 : {
178 0 : const SwAnchoredObject* pAnchoredObj = pContact->GetAnchoredObj( &_rSdrObj );
179 0 : if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
180 : {
181 : const SwAnchoredDrawObject* pAnchoredDrawObj =
182 0 : static_cast<const SwAnchoredDrawObject*>(pAnchoredObj);
183 0 : const SwRect aObjRect = _rSdrObj.GetSnapRect();
184 : const_cast<SwAnchoredDrawObject*>(pAnchoredDrawObj)
185 0 : ->SetLastObjRect( aObjRect.SVRect() );
186 : }
187 : }
188 0 : }
189 :
190 0 : SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
191 : {
192 : // replace marked 'virtual' drawing objects by the corresponding 'master'
193 : // drawing objects.
194 0 : SwDrawView::ReplaceMarkedDrawVirtObjs( rDrawView );
195 :
196 0 : const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
197 0 : SwDrawFrmFmt *pFmt = 0L;
198 0 : SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
199 0 : bool bNoGroup = ( 0 == pObj->GetUpGroup() );
200 0 : SwDrawContact* pNewContact = 0;
201 0 : if( bNoGroup )
202 : {
203 : // Revoke anchor attribute.
204 0 : SwDrawContact *pMyContact = (SwDrawContact*)GetUserCall(pObj);
205 0 : const SwFmtAnchor aAnch( pMyContact->GetFmt()->GetAnchor() );
206 :
207 0 : SwUndoDrawGroup *const pUndo = (!GetIDocumentUndoRedo().DoesUndo())
208 : ? 0
209 0 : : new SwUndoDrawGroup( (sal_uInt16)rMrkList.GetMarkCount() );
210 :
211 : // #i53320#
212 0 : bool bGroupMembersNotPositioned( false );
213 : {
214 : SwAnchoredDrawObject* pAnchoredDrawObj =
215 0 : static_cast<SwAnchoredDrawObject*>(pMyContact->GetAnchoredObj( pObj ));
216 0 : bGroupMembersNotPositioned = pAnchoredDrawObj->NotYetPositioned();
217 : }
218 : // Destroy ContactObjects and formats.
219 0 : for( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
220 : {
221 0 : pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
222 0 : SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
223 :
224 : // #i53320#
225 : #if OSL_DEBUG_LEVEL > 0
226 : SwAnchoredDrawObject* pAnchoredDrawObj =
227 : static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( pObj ));
228 : OSL_ENSURE( bGroupMembersNotPositioned == pAnchoredDrawObj->NotYetPositioned(),
229 : "<SwDoc::GroupSelection(..)> - group members have different positioning status!" );
230 : #endif
231 :
232 0 : pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
233 : // Deletes itself!
234 0 : pContact->Changed(*pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
235 0 : pObj->SetUserCall( 0 );
236 :
237 0 : if( pUndo )
238 0 : pUndo->AddObj( i, pFmt, pObj );
239 : else
240 0 : DelFrmFmt( pFmt );
241 :
242 : // #i45952# - re-introduce position normalization of group member
243 : // objects, because its anchor position is cleared, when they are
244 : // grouped.
245 0 : Point aAnchorPos( pObj->GetAnchorPos() );
246 0 : pObj->NbcSetAnchorPos( Point( 0, 0 ) );
247 0 : pObj->NbcMove( Size( aAnchorPos.getX(), aAnchorPos.getY() ) );
248 : }
249 :
250 : pFmt = MakeDrawFrmFmt( OUString("DrawObject"),
251 0 : GetDfltFrmFmt() );
252 0 : pFmt->SetFmtAttr( aAnch );
253 : // #i36010# - set layout direction of the position
254 : pFmt->SetPositionLayoutDir(
255 0 : text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
256 :
257 0 : rDrawView.GroupMarked();
258 : OSL_ENSURE( rMrkList.GetMarkCount() == 1, "GroupMarked more or none groups." );
259 :
260 0 : SdrObject* pNewGroupObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
261 0 : pNewContact = new SwDrawContact( pFmt, pNewGroupObj );
262 : // #i35635#
263 0 : pNewContact->MoveObjToVisibleLayer( pNewGroupObj );
264 0 : pNewContact->ConnectToLayout();
265 : // #i53320# - No adjustment of the positioning and alignment
266 : // attributes, if group members aren't positioned yet.
267 0 : if ( !bGroupMembersNotPositioned )
268 : {
269 : // #i26791# - Adjust positioning and alignment attributes.
270 0 : lcl_AdjustPositioningAttr( pFmt, *pNewGroupObj );
271 : }
272 :
273 0 : if( pUndo )
274 : {
275 0 : pUndo->SetGroupFmt( pFmt );
276 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
277 0 : }
278 : }
279 : else
280 : {
281 0 : if (GetIDocumentUndoRedo().DoesUndo())
282 : {
283 0 : GetIDocumentUndoRedo().ClearRedo();
284 : }
285 :
286 0 : rDrawView.GroupMarked();
287 : OSL_ENSURE( rMrkList.GetMarkCount() == 1, "GroupMarked more or none groups." );
288 : }
289 :
290 0 : return pNewContact;
291 : }
292 :
293 0 : void SwDoc::UnGroupSelection( SdrView& rDrawView )
294 : {
295 0 : bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
296 0 : if( bUndo )
297 : {
298 0 : GetIDocumentUndoRedo().ClearRedo();
299 : }
300 :
301 : // replace marked 'virtual' drawing objects by the corresponding 'master'
302 : // drawing objects.
303 0 : SwDrawView::ReplaceMarkedDrawVirtObjs( rDrawView );
304 :
305 0 : const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
306 0 : std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >* pFmtsAndObjs( 0L );
307 0 : const sal_uInt32 nMarkCount( rMrkList.GetMarkCount() );
308 0 : if ( nMarkCount )
309 : {
310 0 : pFmtsAndObjs = new std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >[nMarkCount];
311 0 : SdrObject *pMyObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
312 0 : if( !pMyObj->GetUpGroup() )
313 : {
314 0 : OUString sDrwFmtNm("DrawObject");
315 0 : for ( sal_uInt16 i = 0; i < nMarkCount; ++i )
316 : {
317 0 : SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
318 0 : if ( pObj->IsA( TYPE(SdrObjGroup) ) )
319 : {
320 0 : SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
321 0 : SwFmtAnchor aAnch( pContact->GetFmt()->GetAnchor() );
322 0 : SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList();
323 :
324 0 : SwUndoDrawUnGroup* pUndo = 0;
325 0 : if( bUndo )
326 : {
327 0 : pUndo = new SwUndoDrawUnGroup( (SdrObjGroup*)pObj );
328 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
329 : }
330 :
331 0 : for ( sal_uInt16 i2 = 0; i2 < pLst->GetObjCount(); ++i2 )
332 : {
333 0 : SdrObject* pSubObj = pLst->GetObj( i2 );
334 : SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( sDrwFmtNm,
335 0 : GetDfltFrmFmt() );
336 0 : pFmt->SetFmtAttr( aAnch );
337 : // #i36010# - set layout direction of the position
338 : pFmt->SetPositionLayoutDir(
339 0 : text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
340 0 : pFmtsAndObjs[i].push_back( std::pair< SwDrawFrmFmt*, SdrObject* >( pFmt, pSubObj ) );
341 :
342 0 : if( bUndo )
343 0 : pUndo->AddObj( i2, pFmt );
344 0 : }
345 : }
346 0 : }
347 : }
348 : }
349 0 : rDrawView.UnGroupMarked();
350 : // creation of <SwDrawContact> instances for the former group members and
351 : // its connection to the Writer layout.
352 0 : for ( sal_uInt32 i = 0; i < nMarkCount; ++i )
353 : {
354 0 : SwUndoDrawUnGroupConnectToLayout* pUndo = 0;
355 0 : if( bUndo )
356 : {
357 0 : pUndo = new SwUndoDrawUnGroupConnectToLayout();
358 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
359 : }
360 :
361 0 : while ( pFmtsAndObjs[i].size() > 0 )
362 : {
363 0 : SwDrawFrmFmt* pFmt( pFmtsAndObjs[i].back().first );
364 0 : SdrObject* pObj( pFmtsAndObjs[i].back().second );
365 0 : pFmtsAndObjs[i].pop_back();
366 :
367 0 : SwDrawContact* pContact = new SwDrawContact( pFmt, pObj );
368 0 : pContact->MoveObjToVisibleLayer( pObj );
369 0 : pContact->ConnectToLayout();
370 0 : lcl_AdjustPositioningAttr( pFmt, *pObj );
371 :
372 0 : if ( bUndo )
373 : {
374 0 : pUndo->AddFmtAndObj( pFmt, pObj );
375 : }
376 : }
377 : }
378 0 : delete [] pFmtsAndObjs;
379 0 : }
380 :
381 0 : bool SwDoc::DeleteSelection( SwDrawView& rDrawView )
382 : {
383 0 : bool bCallBase = false;
384 0 : const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
385 0 : if( rMrkList.GetMarkCount() )
386 : {
387 0 : GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
388 : sal_uInt16 i;
389 0 : bool bDelMarked = true;
390 :
391 0 : if( 1 == rMrkList.GetMarkCount() )
392 : {
393 0 : SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
394 0 : if( pObj->ISA(SwVirtFlyDrawObj) )
395 : {
396 : SwFlyFrmFmt* pFrmFmt = (SwFlyFrmFmt*)
397 0 : ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetFmt();
398 0 : if( pFrmFmt )
399 : {
400 0 : DelLayoutFmt( pFrmFmt );
401 0 : bDelMarked = false;
402 : }
403 : }
404 : }
405 :
406 0 : for( i = 0; i < rMrkList.GetMarkCount(); ++i )
407 : {
408 0 : SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
409 0 : if( !pObj->ISA(SwVirtFlyDrawObj) )
410 : {
411 0 : SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
412 0 : SwDrawFrmFmt *pFrmFmt = (SwDrawFrmFmt*)pC->GetFmt();
413 0 : if( pFrmFmt &&
414 0 : FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
415 : {
416 0 : rDrawView.MarkObj( pObj, rDrawView.Imp().GetPageView(), true );
417 0 : --i;
418 0 : DelLayoutFmt( pFrmFmt );
419 : }
420 : }
421 : }
422 :
423 0 : if( rMrkList.GetMarkCount() && bDelMarked )
424 : {
425 0 : SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
426 0 : if( !pObj->GetUpGroup() )
427 : {
428 : SwUndoDrawDelete *const pUndo =
429 0 : (!GetIDocumentUndoRedo().DoesUndo())
430 : ? 0
431 0 : : new SwUndoDrawDelete( (sal_uInt16)rMrkList.GetMarkCount() );
432 :
433 : // Destroy ContactObjects, save formats.
434 0 : for( i = 0; i < rMrkList.GetMarkCount(); ++i )
435 : {
436 0 : const SdrMark& rMark = *rMrkList.GetMark( i );
437 0 : pObj = rMark.GetMarkedSdrObj();
438 0 : SwDrawContact *pContact = (SwDrawContact*)pObj->GetUserCall();
439 0 : if( pContact ) // of course not for grouped objects
440 : {
441 0 : SwDrawFrmFmt *pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
442 : // before delete of selection is performed, marked
443 : // <SwDrawVirtObj>-objects have to be replaced by its
444 : // reference objects. Thus, assert, if a
445 : // <SwDrawVirt>-object is found in the mark list.
446 0 : if ( pObj->ISA(SwDrawVirtObj) )
447 : {
448 : OSL_FAIL( "<SwDrawVirtObj> is still marked for delete. application will crash!" );
449 : }
450 : // Deletes itself!
451 0 : pContact->Changed(*pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
452 0 : pObj->SetUserCall( 0 );
453 :
454 0 : if( pUndo )
455 0 : pUndo->AddObj( i, pFmt, rMark );
456 : else
457 0 : DelFrmFmt( pFmt );
458 : }
459 : }
460 :
461 0 : if( pUndo )
462 : {
463 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
464 : }
465 : }
466 0 : bCallBase = true;
467 : }
468 0 : SetModified();
469 :
470 0 : GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
471 : }
472 :
473 0 : return bCallBase;
474 : }
475 :
476 0 : _ZSortFly::_ZSortFly( const SwFrmFmt* pFrmFmt, const SwFmtAnchor* pFlyAn,
477 : sal_uInt32 nArrOrdNum )
478 0 : : pFmt( pFrmFmt ), pAnchor( pFlyAn ), nOrdNum( nArrOrdNum )
479 : {
480 : // #i11176#
481 : // This also needs to work when no layout exists. Thus, for
482 : // FlyFrames an alternative method is used now in that case.
483 0 : if( RES_FLYFRMFMT == pFmt->Which() )
484 : {
485 0 : if( pFmt->getIDocumentLayoutAccess()->GetCurrentViewShell() )
486 : {
487 : // See if there is an SdrObject for it
488 0 : SwFlyFrm* pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement( *pFrmFmt );
489 0 : if( pFly )
490 0 : nOrdNum = pFly->GetVirtDrawObj()->GetOrdNum();
491 : }
492 : else
493 : {
494 : // See if there is an SdrObject for it
495 0 : SwFlyDrawContact* pContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *pFrmFmt );
496 0 : if( pContact )
497 0 : nOrdNum = pContact->GetMaster()->GetOrdNum();
498 : }
499 : }
500 0 : else if( RES_DRAWFRMFMT == pFmt->Which() )
501 : {
502 : // See if there is an SdrObject for it
503 0 : SwDrawContact* pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement( *pFrmFmt );
504 0 : if( pContact )
505 0 : nOrdNum = pContact->GetMaster()->GetOrdNum();
506 : }
507 : else {
508 : OSL_ENSURE( !this, "what is that for a format?" );
509 : }
510 0 : }
511 :
512 : #include <svx/sxenditm.hxx>
513 :
514 : // Is also called by the Sw3 Reader, if there was an error when reading the
515 : // drawing layer. If it is called by the Sw3 Reader the layer is rebuilt
516 : // from scratch.
517 0 : void SwDoc::InitDrawModel()
518 : {
519 : // !! Attention: there is similar code in the Sw3 Reader (sw3imp.cxx) that
520 : // also has to be maintained!!
521 0 : if ( mpDrawModel )
522 0 : ReleaseDrawModel();
523 :
524 : //UUUU
525 : // // Setup DrawPool and EditEnginePool. Ownership is ours and only gets passed
526 : // // to the Drawing.
527 : // // The pools are destroyed in the ReleaseDrawModel.
528 : // // for loading the drawing items. This must be loaded without RefCounts!
529 : // SfxItemPool *pSdrPool = new SdrItemPool( &GetAttrPool() );
530 : // // change DefaultItems for the SdrEdgeObj distance items to TWIPS.
531 : // if(pSdrPool)
532 : // {
533 : // const long nDefEdgeDist = ((500 * 72) / 127); // 1/100th mm in twips
534 : // pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
535 : // pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
536 : // pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
537 : // pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
538 : //
539 : // // #i33700#
540 : // // Set shadow distance defaults as PoolDefaultItems. Details see bug.
541 : // pSdrPool->SetPoolDefaultItem(SdrShadowXDistItem((300 * 72) / 127));
542 : // pSdrPool->SetPoolDefaultItem(SdrShadowYDistItem((300 * 72) / 127));
543 : // }
544 : // SfxItemPool *pEEgPool = EditEngine::CreatePool( false );
545 : // pSdrPool->SetSecondaryPool( pEEgPool );
546 : // if ( !GetAttrPool().GetFrozenIdRanges () )
547 : // GetAttrPool().FreezeIdRanges();
548 : // else
549 : // pSdrPool->FreezeIdRanges();
550 :
551 : // set FontHeight pool defaults without changing static SdrEngineDefaults
552 0 : GetAttrPool().SetPoolDefaultItem(SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ));
553 :
554 : SAL_INFO( "sw.doc", "before create DrawDocument" );
555 : // The document owns the SdrModel. We always have two layers and one page.
556 0 : mpDrawModel = new SwDrawDocument( this );
557 :
558 0 : mpDrawModel->EnableUndo( GetIDocumentUndoRedo().DoesUndo() );
559 :
560 0 : OUString sLayerNm;
561 0 : sLayerNm = "Hell";
562 0 : mnHell = mpDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
563 :
564 0 : sLayerNm = "Heaven";
565 0 : mnHeaven = mpDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
566 :
567 0 : sLayerNm = "Controls";
568 0 : mnControls = mpDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
569 :
570 : // add invisible layers corresponding to the visible ones.
571 : {
572 0 : sLayerNm = "InvisibleHell";
573 0 : mnInvisibleHell = mpDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
574 :
575 0 : sLayerNm = "InvisibleHeaven";
576 0 : mnInvisibleHeaven = mpDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
577 :
578 0 : sLayerNm = "InvisibleControls";
579 0 : mnInvisibleControls = mpDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
580 : }
581 :
582 0 : SdrPage* pMasterPage = mpDrawModel->AllocPage( false );
583 0 : mpDrawModel->InsertPage( pMasterPage );
584 : SAL_INFO( "sw.doc", "after create DrawDocument" );
585 : SAL_INFO( "sw.doc", "before create Spellchecker/Hyphenator" );
586 0 : SdrOutliner& rOutliner = mpDrawModel->GetDrawOutliner();
587 0 : uno::Reference< XSpellChecker1 > xSpell = ::GetSpellChecker();
588 0 : rOutliner.SetSpeller( xSpell );
589 0 : uno::Reference<XHyphenator> xHyphenator( ::GetHyphenator() );
590 0 : rOutliner.SetHyphenator( xHyphenator );
591 : SAL_INFO( "sw.doc", "after create Spellchecker/Hyphenator" );
592 0 : SetCalcFieldValueHdl(&rOutliner);
593 0 : SetCalcFieldValueHdl(&mpDrawModel->GetHitTestOutliner());
594 :
595 : // Set the LinkManager in the model so that linked graphics can be inserted.
596 : // The WinWord import needs it too.
597 0 : mpDrawModel->SetLinkManager( &GetLinkManager() );
598 0 : mpDrawModel->SetAddExtLeading( get(IDocumentSettingAccess::ADD_EXT_LEADING) );
599 :
600 0 : OutputDevice* pRefDev = getReferenceDevice( false );
601 0 : if ( pRefDev )
602 0 : mpDrawModel->SetRefDevice( pRefDev );
603 :
604 0 : mpDrawModel->SetNotifyUndoActionHdl( LINK( this, SwDoc, AddDrawUndo ));
605 0 : if ( mpCurrentView )
606 : {
607 0 : SwViewShell* pViewSh = mpCurrentView;
608 0 : do
609 : {
610 0 : SwRootFrm* pRoot = pViewSh->GetLayout();
611 0 : if( pRoot && !pRoot->GetDrawPage() )
612 : {
613 : // Disable "multiple layout" for the moment:
614 : // use pMasterPage instead of a new created SdrPage
615 : // mpDrawModel->AllocPage( FALSE );
616 : // mpDrawModel->InsertPage( pDrawPage );
617 0 : SdrPage* pDrawPage = pMasterPage;
618 0 : pRoot->SetDrawPage( pDrawPage );
619 0 : pDrawPage->SetSize( pRoot->Frm().SSize() );
620 : }
621 0 : pViewSh = (SwViewShell*)pViewSh->GetNext();
622 0 : }while( pViewSh != mpCurrentView );
623 0 : }
624 0 : }
625 :
626 : /** method to notify drawing page view about the invisible layers */
627 0 : void SwDoc::NotifyInvisibleLayers( SdrPageView& _rSdrPageView )
628 : {
629 0 : OUString sLayerNm;
630 0 : sLayerNm = "InvisibleHell";
631 0 : _rSdrPageView.SetLayerVisible( sLayerNm, false );
632 :
633 0 : sLayerNm = "InvisibleHeaven";
634 0 : _rSdrPageView.SetLayerVisible( sLayerNm, false );
635 :
636 0 : sLayerNm = "InvisibleControls";
637 0 : _rSdrPageView.SetLayerVisible( sLayerNm, false );
638 0 : }
639 :
640 : /** method to determine, if a layer ID belongs to the visible ones.
641 :
642 : @note If given layer ID is unknown, method asserts and returns <false>.
643 : */
644 0 : bool SwDoc::IsVisibleLayerId( const SdrLayerID& _nLayerId ) const
645 : {
646 : bool bRetVal;
647 :
648 0 : if ( _nLayerId == GetHeavenId() ||
649 0 : _nLayerId == GetHellId() ||
650 0 : _nLayerId == GetControlsId() )
651 : {
652 0 : bRetVal = true;
653 : }
654 0 : else if ( _nLayerId == GetInvisibleHeavenId() ||
655 0 : _nLayerId == GetInvisibleHellId() ||
656 0 : _nLayerId == GetInvisibleControlsId() )
657 : {
658 0 : bRetVal = false;
659 : }
660 : else
661 : {
662 : OSL_FAIL( "<SwDoc::IsVisibleLayerId(..)> - unknown layer ID." );
663 0 : bRetVal = false;
664 : }
665 :
666 0 : return bRetVal;
667 : }
668 :
669 : /** method to determine, if the corresponding visible layer ID for a invisible one.
670 :
671 : @note If given layer ID is a visible one, method returns given layer ID.
672 : @note If given layer ID is unknown, method returns given layer ID.
673 : */
674 0 : SdrLayerID SwDoc::GetVisibleLayerIdByInvisibleOne( const SdrLayerID& _nInvisibleLayerId )
675 : {
676 : SdrLayerID nVisibleLayerId;
677 :
678 0 : if ( _nInvisibleLayerId == GetInvisibleHeavenId() )
679 : {
680 0 : nVisibleLayerId = GetHeavenId();
681 : }
682 0 : else if ( _nInvisibleLayerId == GetInvisibleHellId() )
683 : {
684 0 : nVisibleLayerId = GetHellId();
685 : }
686 0 : else if ( _nInvisibleLayerId == GetInvisibleControlsId() )
687 : {
688 0 : nVisibleLayerId = GetControlsId();
689 : }
690 0 : else if ( _nInvisibleLayerId == GetHeavenId() ||
691 0 : _nInvisibleLayerId == GetHellId() ||
692 0 : _nInvisibleLayerId == GetControlsId() )
693 : {
694 : OSL_FAIL( "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID already an invisible one." );
695 0 : nVisibleLayerId = _nInvisibleLayerId;
696 : }
697 : else
698 : {
699 : OSL_FAIL( "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID is unknown." );
700 0 : nVisibleLayerId = _nInvisibleLayerId;
701 : }
702 :
703 0 : return nVisibleLayerId;
704 : }
705 :
706 : /** method to determine, if the corresponding invisible layer ID for a visible one.
707 :
708 : @note If given layer ID is a invisible one, method returns given layer ID.
709 : @note If given layer ID is unknown, method returns given layer ID.
710 : */
711 0 : SdrLayerID SwDoc::GetInvisibleLayerIdByVisibleOne( const SdrLayerID& _nVisibleLayerId )
712 : {
713 : SdrLayerID nInvisibleLayerId;
714 :
715 0 : if ( _nVisibleLayerId == GetHeavenId() )
716 : {
717 0 : nInvisibleLayerId = GetInvisibleHeavenId();
718 : }
719 0 : else if ( _nVisibleLayerId == GetHellId() )
720 : {
721 0 : nInvisibleLayerId = GetInvisibleHellId();
722 : }
723 0 : else if ( _nVisibleLayerId == GetControlsId() )
724 : {
725 0 : nInvisibleLayerId = GetInvisibleControlsId();
726 : }
727 0 : else if ( _nVisibleLayerId == GetInvisibleHeavenId() ||
728 0 : _nVisibleLayerId == GetInvisibleHellId() ||
729 0 : _nVisibleLayerId == GetInvisibleControlsId() )
730 : {
731 : OSL_FAIL( "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID already an invisible one." );
732 0 : nInvisibleLayerId = _nVisibleLayerId;
733 : }
734 : else
735 : {
736 : OSL_FAIL( "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID is unknown." );
737 0 : nInvisibleLayerId = _nVisibleLayerId;
738 : }
739 :
740 0 : return nInvisibleLayerId;
741 : }
742 :
743 0 : void SwDoc::ReleaseDrawModel()
744 : {
745 0 : if ( mpDrawModel )
746 : {
747 : // !! Also maintain the code in the sw3io for inserting documents!!
748 :
749 0 : delete mpDrawModel; mpDrawModel = 0;
750 : //UUUU
751 : // SfxItemPool *pSdrPool = GetAttrPool().GetSecondaryPool();
752 : //
753 : // OSL_ENSURE( pSdrPool, "missing pool" );
754 : // SfxItemPool *pEEgPool = pSdrPool->GetSecondaryPool();
755 : // OSL_ENSURE( !pEEgPool->GetSecondaryPool(), "I don't accept additional pools");
756 : // pSdrPool->Delete(); // First have the items destroyed,
757 : // // then destroy the chain!
758 : // GetAttrPool().SetSecondaryPool( 0 ); // This one's a must!
759 : // pSdrPool->SetSecondaryPool( 0 ); // That one's safer
760 : // SfxItemPool::Free(pSdrPool);
761 : // SfxItemPool::Free(pEEgPool);
762 : }
763 0 : }
764 :
765 0 : SdrModel* SwDoc::_MakeDrawModel()
766 : {
767 : OSL_ENSURE( !mpDrawModel, "_MakeDrawModel: Why?" );
768 0 : InitDrawModel();
769 0 : if ( mpCurrentView )
770 : {
771 0 : SwViewShell* pTmp = mpCurrentView;
772 0 : do
773 : {
774 0 : pTmp->MakeDrawView();
775 0 : pTmp = (SwViewShell*) pTmp->GetNext();
776 0 : } while ( pTmp != mpCurrentView );
777 :
778 : // Broadcast, so that the FormShell can be connected to the DrawView
779 0 : if( GetDocShell() )
780 : {
781 0 : SfxSimpleHint aHnt( SW_BROADCAST_DRAWVIEWS_CREATED );
782 0 : GetDocShell()->Broadcast( aHnt );
783 : }
784 : }
785 0 : return mpDrawModel;
786 : }
787 :
788 0 : void SwDoc::DrawNotifyUndoHdl()
789 : {
790 0 : mpDrawModel->SetNotifyUndoActionHdl( Link() );
791 0 : }
792 :
793 : /// In the Outliner, set a link to the method for field display in edit objects.
794 0 : void SwDoc::SetCalcFieldValueHdl(Outliner* pOutliner)
795 : {
796 0 : pOutliner->SetCalcFieldValueHdl(LINK(this, SwDoc, CalcFieldValueHdl));
797 0 : }
798 :
799 : /// Recognise fields/URLs in the Outliner and set how they are displayed.
800 0 : IMPL_LINK(SwDoc, CalcFieldValueHdl, EditFieldInfo*, pInfo)
801 : {
802 0 : if (pInfo)
803 : {
804 0 : const SvxFieldItem& rField = pInfo->GetField();
805 0 : const SvxFieldData* pField = rField.GetField();
806 :
807 0 : if (pField && pField->ISA(SvxDateField))
808 : {
809 : // Date field
810 : pInfo->SetRepresentation(
811 : ((const SvxDateField*) pField)->GetFormatted(
812 0 : *GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
813 : }
814 0 : else if (pField && pField->ISA(SvxURLField))
815 : {
816 : // URL field
817 0 : switch ( ((const SvxURLField*) pField)->GetFormat() )
818 : {
819 : case SVXURLFORMAT_APPDEFAULT: //!!! Can be set in App???
820 : case SVXURLFORMAT_REPR:
821 : {
822 : pInfo->SetRepresentation(
823 0 : ((const SvxURLField*)pField)->GetRepresentation());
824 : }
825 0 : break;
826 :
827 : case SVXURLFORMAT_URL:
828 : {
829 : pInfo->SetRepresentation(
830 0 : ((const SvxURLField*)pField)->GetURL());
831 : }
832 0 : break;
833 : }
834 :
835 : sal_uInt16 nChrFmt;
836 :
837 0 : if (IsVisitedURL(((const SvxURLField*)pField)->GetURL()))
838 0 : nChrFmt = RES_POOLCHR_INET_VISIT;
839 : else
840 0 : nChrFmt = RES_POOLCHR_INET_NORMAL;
841 :
842 0 : SwFmt *pFmt = GetCharFmtFromPool(nChrFmt);
843 :
844 0 : Color aColor(COL_LIGHTBLUE);
845 0 : if (pFmt)
846 0 : aColor = pFmt->GetColor().GetValue();
847 :
848 0 : pInfo->SetTxtColor(aColor);
849 : }
850 0 : else if (pField && pField->ISA(SdrMeasureField))
851 : {
852 : // Measure field
853 0 : pInfo->ClearFldColor();
854 : }
855 0 : else if ( pField && pField->ISA(SvxExtTimeField))
856 : {
857 : // Time field
858 : pInfo->SetRepresentation(
859 : ((const SvxExtTimeField*) pField)->GetFormatted(
860 0 : *GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
861 : }
862 : else
863 : {
864 : OSL_FAIL("unknown field command");
865 0 : pInfo->SetRepresentation( OUString( '?' ) );
866 : }
867 : }
868 :
869 0 : return(0);
870 : }
871 :
872 : /* TFFDI: The functions formerly declared 'inline'
873 : */
874 0 : const SdrModel* SwDoc::GetDrawModel() const { return mpDrawModel; }
875 0 : SdrModel* SwDoc::GetDrawModel() { return mpDrawModel; }
876 0 : SdrLayerID SwDoc::GetHeavenId() const { return mnHeaven; }
877 0 : SdrLayerID SwDoc::GetHellId() const { return mnHell; }
878 0 : SdrLayerID SwDoc::GetControlsId() const { return mnControls; }
879 0 : SdrLayerID SwDoc::GetInvisibleHeavenId() const { return mnInvisibleHeaven; }
880 0 : SdrLayerID SwDoc::GetInvisibleHellId() const { return mnInvisibleHell; }
881 0 : SdrLayerID SwDoc::GetInvisibleControlsId() const { return mnInvisibleControls; }
882 0 : SdrModel* SwDoc::GetOrCreateDrawModel() { return GetDrawModel() ? GetDrawModel() : _MakeDrawModel(); }
883 :
884 : // #i62875#
885 : namespace docfunc
886 : {
887 0 : bool ExistsDrawObjs( SwDoc& p_rDoc )
888 : {
889 0 : bool bExistsDrawObjs( false );
890 :
891 0 : if ( p_rDoc.GetDrawModel() &&
892 0 : p_rDoc.GetDrawModel()->GetPage( 0 ) )
893 : {
894 0 : const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
895 :
896 0 : SdrObjListIter aIter( rSdrPage, IM_FLAT );
897 0 : while( aIter.IsMore() )
898 : {
899 0 : SdrObject* pObj( aIter.Next() );
900 0 : if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
901 0 : !dynamic_cast<SwFlyDrawObj*>(pObj) )
902 : {
903 0 : bExistsDrawObjs = true;
904 0 : break;
905 : }
906 0 : }
907 : }
908 :
909 0 : return bExistsDrawObjs;
910 : }
911 :
912 0 : bool AllDrawObjsOnPage( SwDoc& p_rDoc )
913 : {
914 0 : bool bAllDrawObjsOnPage( true );
915 :
916 0 : if ( p_rDoc.GetDrawModel() &&
917 0 : p_rDoc.GetDrawModel()->GetPage( 0 ) )
918 : {
919 0 : const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
920 :
921 0 : SdrObjListIter aIter( rSdrPage, IM_FLAT );
922 0 : while( aIter.IsMore() )
923 : {
924 0 : SdrObject* pObj( aIter.Next() );
925 0 : if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
926 0 : !dynamic_cast<SwFlyDrawObj*>(pObj) )
927 : {
928 : SwDrawContact* pDrawContact =
929 0 : dynamic_cast<SwDrawContact*>(::GetUserCall( pObj ));
930 0 : if ( pDrawContact )
931 : {
932 : SwAnchoredDrawObject* pAnchoredDrawObj =
933 0 : dynamic_cast<SwAnchoredDrawObject*>(pDrawContact->GetAnchoredObj( pObj ));
934 :
935 : // error handling
936 : {
937 0 : if ( !pAnchoredDrawObj )
938 : {
939 : OSL_FAIL( "<docfunc::AllDrawObjsOnPage() - missing anchored draw object" );
940 0 : bAllDrawObjsOnPage = false;
941 0 : break;
942 : }
943 : }
944 :
945 0 : if ( pAnchoredDrawObj->NotYetPositioned() )
946 : {
947 : // The drawing object isn't yet layouted.
948 : // Thus, it isn't known, if all drawing objects are on page.
949 0 : bAllDrawObjsOnPage = false;
950 0 : break;
951 : }
952 0 : else if ( pAnchoredDrawObj->IsOutsidePage() )
953 : {
954 0 : bAllDrawObjsOnPage = false;
955 0 : break;
956 : }
957 : }
958 : else
959 : {
960 : // contact object of drawing object doesn't exists.
961 : // Thus, the drawing object isn't yet positioned.
962 : // Thus, it isn't known, if all drawing objects are on page.
963 0 : bAllDrawObjsOnPage = false;
964 0 : break;
965 : }
966 : }
967 0 : }
968 : }
969 :
970 0 : return bAllDrawObjsOnPage;
971 : }
972 : }
973 :
974 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|