1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <sfx2/viewfrm.hxx>
26 #include <svx/svxids.hrc>
27 #include <svx/dialogs.hrc>
28 #include <svl/itempool.hxx>
29 #include <vcl/layout.hxx>
30 #include <sfx2/request.hxx>
31 #include <svl/stritem.hxx>
32 #include <vcl/prntypes.hxx>
33 #include <svl/style.hxx>
34 #include <stlsheet.hxx>
35 #include <svx/svdorect.hxx>
36 #include <svx/svdundo.hxx>
37 #include <editeng/eeitem.hxx>
38 #include <editeng/frmdiritem.hxx>
39 #include <svx/graphichelper.hxx>
40 #include <svx/xbtmpit.hxx>
41 #include <svx/xsetit.hxx>
42 #include <editeng/ulspitem.hxx>
43 #include <editeng/lrspitem.hxx>
44 #include <svx/sdr/properties/properties.hxx>
45 #include <sfx2/bindings.hxx>
46 #include <editeng/shaditem.hxx>
47 #include <editeng/boxitem.hxx>
48 #include <editeng/sizeitem.hxx>
49 #include <editeng/pbinitem.hxx>
50 #include <sfx2/app.hxx>
51 #include <sfx2/opengrf.hxx>
53 #include <strings.hrc>
58 #include <drawdoc.hxx>
59 #include <DrawDocShell.hxx>
60 #include <ViewShell.hxx>
61 #include <ViewShellBase.hxx>
62 #include <DrawViewShell.hxx>
65 #include <undoback.hxx>
66 #include <sdabstdlg.hxx>
67 #include <sdresid.hxx>
68 #include <sdundogr.hxx>
73 using namespace com::sun::star
;
75 namespace vcl
{ class Window
; }
80 // adapted from writer
81 #define MAXHEIGHT 28350
82 #define MAXWIDTH 28350
85 void mergeItemSetsImpl( SfxItemSet
& rTarget
, const SfxItemSet
& rSource
)
87 const sal_uInt16
* pPtr
= rSource
.GetRanges();
94 // make ranges discrete
95 while(pPtr
[2] && (pPtr
[2] - p2
== 1))
100 rTarget
.MergeRange( p1
, p2
);
104 rTarget
.Put(rSource
);
107 FuPage::FuPage( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
,
108 SdDrawDocument
* pDoc
, SfxRequest
& rReq
)
109 : FuPoor(pViewSh
, pWin
, pView
, pDoc
, rReq
),
111 mpArgs( rReq
.GetArgs() ),
112 mpBackgroundObjUndoAction( nullptr ),
113 mbPageBckgrdDeleted( false ),
114 mbMasterPage( false ),
115 mbDisplayBackgroundTabPage( true ),
117 mpDrawViewShell(nullptr)
121 rtl::Reference
<FuPoor
> FuPage::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
)
123 rtl::Reference
<FuPoor
> xFunc( new FuPage( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
124 xFunc
->DoExecute(rReq
);
128 void FuPage::DoExecute( SfxRequest
& )
130 mpDrawViewShell
= dynamic_cast<DrawViewShell
*>(mpViewShell
);
131 DBG_ASSERT( mpDrawViewShell
, "sd::FuPage::FuPage(), called without a current DrawViewShell!" );
133 if( mpDrawViewShell
)
135 mbMasterPage
= mpDrawViewShell
->GetEditMode() == EditMode::MasterPage
;
136 // we don't really want to format page background with SID_ATTR_PAGE[_SIZE] slots
137 mbDisplayBackgroundTabPage
= ( mpDrawViewShell
->GetPageKind() == PageKind::Standard
) &&
138 ( nSlotId
!= SID_ATTR_PAGE_SIZE
) && ( nSlotId
!= SID_ATTR_PAGE
);
139 mpPage
= mpDrawViewShell
->getCurrentPage();
144 // if there are no arguments given, open the dialog
147 mpView
->SdrEndTextEdit();
148 mpArgs
= ExecuteDialog(mpWindow
? mpWindow
->GetFrameWeld() : nullptr);
151 // if we now have arguments, apply them to current page
154 ApplyItemSet( mpArgs
);
163 void FuPage::Activate()
167 void FuPage::Deactivate()
171 void MergePageBackgroundFilling(SdPage
*pPage
, SdStyleSheet
*pStyleSheet
, bool bMasterPage
, SfxItemSet
& rMergedAttr
)
176 mergeItemSetsImpl(rMergedAttr
, pStyleSheet
->GetItemSet());
180 // Only this page, get attributes for background fill
181 const SfxItemSet
& rBackgroundAttributes
= pPage
->getSdrPageProperties().GetItemSet();
183 if(drawing::FillStyle_NONE
!= rBackgroundAttributes
.Get(XATTR_FILLSTYLE
).GetValue())
185 // page attributes are used, take them
186 rMergedAttr
.Put(rBackgroundAttributes
);
191 && drawing::FillStyle_NONE
!= pStyleSheet
->GetItemSet().Get(XATTR_FILLSTYLE
).GetValue())
193 // if the page has no fill style, use the settings from the
194 // background stylesheet (if used)
195 mergeItemSetsImpl(rMergedAttr
, pStyleSheet
->GetItemSet());
199 // no fill style from page, start with no fill style
200 rMergedAttr
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
206 const SfxItemSet
* FuPage::ExecuteDialog(weld::Window
* pParent
)
208 if (!mpDrawViewShell
)
211 SfxItemSet
aNewAttr(mpDoc
->GetPool(),
212 {{mpDoc
->GetPool().GetWhich(SID_ATTR_LRSPACE
),
213 mpDoc
->GetPool().GetWhich(SID_ATTR_ULSPACE
)},
214 {SID_ATTR_PAGE
, SID_ATTR_PAGE_SHARED
},
215 {SID_ATTR_BORDER_OUTER
, SID_ATTR_BORDER_OUTER
},
216 {SID_ATTR_BORDER_SHADOW
, SID_ATTR_BORDER_SHADOW
},
217 {XATTR_FILL_FIRST
, XATTR_FILL_LAST
},
218 {SID_ATTR_PAGE_COLOR
,SID_ATTR_PAGE_FILLSTYLE
},
219 {EE_PARA_WRITINGDIR
, EE_PARA_WRITINGDIR
}});
221 // Retrieve additional data for dialog
223 SvxShadowItem
aShadowItem(SID_ATTR_BORDER_SHADOW
);
224 aNewAttr
.Put( aShadowItem
);
225 SvxBoxItem
aBoxItem( SID_ATTR_BORDER_OUTER
);
226 aNewAttr
.Put( aBoxItem
);
228 aNewAttr
.Put( SvxFrameDirectionItem(
229 mpDoc
->GetDefaultWritingMode() == css::text::WritingMode_RL_TB
? SvxFrameDirection::Horizontal_RL_TB
: SvxFrameDirection::Horizontal_LR_TB
,
230 EE_PARA_WRITINGDIR
) );
232 // Retrieve page-data for dialog
234 SvxPageItem
aPageItem( SID_ATTR_PAGE
);
235 aPageItem
.SetDescName( mpPage
->GetName() );
236 aPageItem
.SetPageUsage( SvxPageUsage::All
);
237 aPageItem
.SetLandscape( mpPage
->GetOrientation() == Orientation::Landscape
);
238 aPageItem
.SetNumType( mpDoc
->GetPageNumType() );
239 aNewAttr
.Put( aPageItem
);
242 maSize
= mpPage
->GetSize();
243 SvxSizeItem
aSizeItem( SID_ATTR_PAGE_SIZE
, maSize
);
244 aNewAttr
.Put( aSizeItem
);
247 SvxSizeItem
aMaxSizeItem( SID_ATTR_PAGE_MAXSIZE
, Size( MAXWIDTH
, MAXHEIGHT
) );
248 aNewAttr
.Put( aMaxSizeItem
);
251 SvxPaperBinItem
aPaperBinItem( SID_ATTR_PAGE_PAPERBIN
, static_cast<sal_uInt8
>(mpPage
->GetPaperBin()) );
252 aNewAttr
.Put( aPaperBinItem
);
254 SvxLRSpaceItem
aLRSpaceItem( static_cast<sal_uInt16
>(mpPage
->GetLeftBorder()), static_cast<sal_uInt16
>(mpPage
->GetRightBorder()), 0, 0, mpDoc
->GetPool().GetWhich(SID_ATTR_LRSPACE
));
255 aNewAttr
.Put( aLRSpaceItem
);
257 SvxULSpaceItem
aULSpaceItem( static_cast<sal_uInt16
>(mpPage
->GetUpperBorder()), static_cast<sal_uInt16
>(mpPage
->GetLowerBorder()), mpDoc
->GetPool().GetWhich(SID_ATTR_ULSPACE
));
258 aNewAttr
.Put( aULSpaceItem
);
261 bool bScale
= mpDoc
->GetDocumentType() != DocumentType::Draw
;
262 aNewAttr
.Put( SfxBoolItem( SID_ATTR_PAGE_EXT1
, bScale
) );
264 bool bFullSize
= mpPage
->IsMasterPage() ?
265 mpPage
->IsBackgroundFullSize() : static_cast<SdPage
&>(mpPage
->TRG_GetMasterPage()).IsBackgroundFullSize();
267 aNewAttr
.Put( SfxBoolItem( SID_ATTR_PAGE_EXT2
, bFullSize
) );
269 // Merge ItemSet for dialog
271 const sal_uInt16
* pPtr
= aNewAttr
.GetRanges();
272 sal_uInt16 p1
= pPtr
[0], p2
= pPtr
[1];
273 while(pPtr
[2] && (pPtr
[2] - p2
== 1))
278 SfxItemSet
aMergedAttr( *aNewAttr
.GetPool(), {{p1
, p2
}} );
280 mergeItemSetsImpl( aMergedAttr
, aNewAttr
);
282 SdStyleSheet
* pStyleSheet
= mpPage
->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND
);
284 // merge page background filling to the dialogs input set
285 if( mbDisplayBackgroundTabPage
)
287 MergePageBackgroundFilling(mpPage
, pStyleSheet
, mbMasterPage
, aMergedAttr
);
290 std::unique_ptr
< SfxItemSet
> pTempSet
;
292 const sal_uInt16 nId
= GetSlotID();
293 if (nId
== SID_SAVE_BACKGROUND
)
295 const XFillStyleItem
& rStyleItem
= aMergedAttr
.Get(XATTR_FILLSTYLE
);
296 if (drawing::FillStyle_BITMAP
== rStyleItem
.GetValue())
298 const XFillBitmapItem
& rBitmap
= aMergedAttr
.Get(XATTR_FILLBITMAP
);
299 const GraphicObject
& rGraphicObj
= rBitmap
.GetGraphicObject();
300 GraphicHelper::ExportGraphic(pParent
, rGraphicObj
.GetGraphic(), "");
303 else if (nId
== SID_SELECT_BACKGROUND
)
305 SvxOpenGraphicDialog
aDlg(SdResId(STR_SET_BACKGROUND_PICTURE
), pParent
);
307 if( aDlg
.Execute() == ERRCODE_NONE
)
310 ErrCode nError
= aDlg
.GetGraphic(aGraphic
);
311 if( nError
== ERRCODE_NONE
)
313 pTempSet
.reset( new SfxItemSet( mpDoc
->GetPool(), svl::Items
<XATTR_FILL_FIRST
, XATTR_FILL_LAST
>{}) );
315 pTempSet
->Put( XFillStyleItem( drawing::FillStyle_BITMAP
) );
317 // MigrateItemSet makes sure the XFillBitmapItem will have a unique name
318 SfxItemSet
aMigrateSet( mpDoc
->GetPool(), svl::Items
<XATTR_FILLBITMAP
, XATTR_FILLBITMAP
>{} );
319 aMigrateSet
.Put(XFillBitmapItem("background", aGraphic
));
320 SdrModel::MigrateItemSet( &aMigrateSet
, pTempSet
.get(), mpDoc
);
322 pTempSet
->Put( XFillBmpStretchItem( true ));
323 pTempSet
->Put( XFillBmpTileItem( false ));
331 SdAbstractDialogFactory
* pFact
= SdAbstractDialogFactory::Create();
332 ScopedVclPtr
<SfxAbstractTabDialog
> pDlg( pFact
? pFact
->CreateSdTabPageDialog(mpViewShell
->GetActiveWindow(), &aMergedAttr
, mpDocSh
, mbDisplayBackgroundTabPage
) : nullptr );
333 if( pDlg
.get() && pDlg
->Execute() == RET_OK
)
334 pTempSet
.reset( new SfxItemSet(*pDlg
->GetOutputItemSet()) );
337 if (pTempSet
.get() && pStyleSheet
)
339 pStyleSheet
->AdjustToFontHeight(*pTempSet
);
341 if( mbDisplayBackgroundTabPage
)
343 // if some fillstyle-items are not set in the dialog, then
344 // try to use the items before
345 bool bChanges
= false;
346 for( sal_uInt16 i
=XATTR_FILL_FIRST
; i
<XATTR_FILL_LAST
; i
++ )
348 if( aMergedAttr
.GetItemState( i
) != SfxItemState::DEFAULT
)
350 if( pTempSet
->GetItemState( i
) == SfxItemState::DEFAULT
)
351 pTempSet
->Put( aMergedAttr
.Get( i
) );
353 if( aMergedAttr
.GetItem( i
) != pTempSet
->GetItem( i
) )
358 // if the background for this page was set to invisible, the background-object has to be deleted, too.
359 if( ( pTempSet
->GetItem
<XFillStyleItem
>( XATTR_FILLSTYLE
)->GetValue() == drawing::FillStyle_NONE
) ||
360 ( ( pTempSet
->GetItemState( XATTR_FILLSTYLE
) == SfxItemState::DEFAULT
) &&
361 ( aMergedAttr
.GetItem
<XFillStyleItem
>( XATTR_FILLSTYLE
)->GetValue() == drawing::FillStyle_NONE
) ) )
362 mbPageBckgrdDeleted
= true;
364 if( !mbMasterPage
&& bChanges
&& mbPageBckgrdDeleted
)
366 mpBackgroundObjUndoAction
.reset( new SdBackgroundObjUndoAction(
367 *mpDoc
, *mpPage
, mpPage
->getSdrPageProperties().GetItemSet()) );
369 if(!mpPage
->IsMasterPage())
371 // on normal pages, switch off fill attribute usage
372 SdrPageProperties
& rPageProperties
= mpPage
->getSdrPageProperties();
373 rPageProperties
.ClearItem( XATTR_FILLBITMAP
);
374 rPageProperties
.ClearItem( XATTR_FILLGRADIENT
);
375 rPageProperties
.ClearItem( XATTR_FILLHATCH
);
376 rPageProperties
.PutItem(XFillStyleItem(drawing::FillStyle_NONE
));
381 /* Special treatment: reset the INVALIDS to
382 NULL-Pointer (otherwise INVALIDs or pointer point
383 to DefaultItems in the template; both would
384 prevent the attribute inheritance) */
385 pTempSet
->ClearInvalidItems();
389 StyleSheetUndoAction
* pAction
= new StyleSheetUndoAction(mpDoc
, static_cast<SfxStyleSheet
*>(pStyleSheet
), &(*pTempSet
.get()));
390 mpDocSh
->GetUndoManager()->AddUndoAction(pAction
);
391 pStyleSheet
->GetItemSet().Put( *(pTempSet
.get()) );
392 sdr::properties::CleanupFillProperties( pStyleSheet
->GetItemSet() );
393 pStyleSheet
->Broadcast(SfxHint(SfxHintId::DataChanged
));
396 // if background filling is set to master pages then clear from page set
399 for( sal_uInt16 nWhich
= XATTR_FILL_FIRST
; nWhich
<= XATTR_FILL_LAST
; nWhich
++ )
401 pTempSet
->ClearItem( nWhich
);
403 pTempSet
->Put(XFillStyleItem(drawing::FillStyle_NONE
));
406 const SfxPoolItem
*pItem
;
407 if( SfxItemState::SET
== pTempSet
->GetItemState( EE_PARA_WRITINGDIR
, false, &pItem
) )
409 SvxFrameDirection nVal
= static_cast<const SvxFrameDirectionItem
*>(pItem
)->GetValue();
410 mpDoc
->SetDefaultWritingMode( nVal
== SvxFrameDirection::Horizontal_RL_TB
? css::text::WritingMode_RL_TB
: css::text::WritingMode_LR_TB
);
415 // BackgroundFill of Masterpage: no hard attributes allowed
416 SdrPage
& rUsedMasterPage
= mpPage
->IsMasterPage() ? *mpPage
: mpPage
->TRG_GetMasterPage();
417 OSL_ENSURE(rUsedMasterPage
.IsMasterPage(), "No MasterPage (!)");
418 rUsedMasterPage
.getSdrPageProperties().ClearItem();
419 OSL_ENSURE(nullptr != rUsedMasterPage
.getSdrPageProperties().GetStyleSheet(),
420 "MasterPage without StyleSheet detected (!)");
423 aNewAttr
.Put(*(pTempSet
.get()));
424 mrReq
.Done( aNewAttr
);
426 return mrReq
.GetArgs();
434 void FuPage::ApplyItemSet( const SfxItemSet
* pArgs
)
436 if (!pArgs
|| !mpDrawViewShell
)
439 // Set new page-attributes
440 PageKind ePageKind
= mpDrawViewShell
->GetPageKind();
441 const SfxPoolItem
* pPoolItem
;
442 bool bSetPageSizeAndBorder
= false;
443 Size
aNewSize(maSize
);
444 sal_Int32 nLeft
= -1, nRight
= -1, nUpper
= -1, nLower
= -1;
445 bool bScaleAll
= true;
446 Orientation eOrientation
= mpPage
->GetOrientation();
447 SdPage
* pMasterPage
= mpPage
->IsMasterPage() ? mpPage
: &static_cast<SdPage
&>(mpPage
->TRG_GetMasterPage());
448 bool bFullSize
= pMasterPage
->IsBackgroundFullSize();
449 sal_uInt16 nPaperBin
= mpPage
->GetPaperBin();
451 if( pArgs
->GetItemState(SID_ATTR_PAGE
, true, &pPoolItem
) == SfxItemState::SET
)
453 mpDoc
->SetPageNumType(static_cast<const SvxPageItem
*>(pPoolItem
)->GetNumType());
455 eOrientation
= static_cast<const SvxPageItem
*>(pPoolItem
)->IsLandscape() ?
456 Orientation::Landscape
: Orientation::Portrait
;
458 if( mpPage
->GetOrientation() != eOrientation
)
459 bSetPageSizeAndBorder
= true;
461 mpDrawViewShell
->ResetActualPage();
464 if( pArgs
->GetItemState(SID_ATTR_PAGE_SIZE
, true, &pPoolItem
) == SfxItemState::SET
)
466 aNewSize
= static_cast<const SvxSizeItem
*>(pPoolItem
)->GetSize();
468 if( mpPage
->GetSize() != aNewSize
)
469 bSetPageSizeAndBorder
= true;
472 if( pArgs
->GetItemState(mpDoc
->GetPool().GetWhich(SID_ATTR_LRSPACE
),
473 true, &pPoolItem
) == SfxItemState::SET
)
475 nLeft
= static_cast<const SvxLRSpaceItem
*>(pPoolItem
)->GetLeft();
476 nRight
= static_cast<const SvxLRSpaceItem
*>(pPoolItem
)->GetRight();
478 if( mpPage
->GetLeftBorder() != nLeft
|| mpPage
->GetRightBorder() != nRight
)
479 bSetPageSizeAndBorder
= true;
483 if( pArgs
->GetItemState(mpDoc
->GetPool().GetWhich(SID_ATTR_ULSPACE
),
484 true, &pPoolItem
) == SfxItemState::SET
)
486 nUpper
= static_cast<const SvxULSpaceItem
*>(pPoolItem
)->GetUpper();
487 nLower
= static_cast<const SvxULSpaceItem
*>(pPoolItem
)->GetLower();
489 if( mpPage
->GetUpperBorder() != nUpper
|| mpPage
->GetLowerBorder() != nLower
)
490 bSetPageSizeAndBorder
= true;
493 if( pArgs
->GetItemState(mpDoc
->GetPool().GetWhich(SID_ATTR_PAGE_EXT1
), true, &pPoolItem
) == SfxItemState::SET
)
495 bScaleAll
= static_cast<const SfxBoolItem
*>(pPoolItem
)->GetValue();
498 if( pArgs
->GetItemState(mpDoc
->GetPool().GetWhich(SID_ATTR_PAGE_EXT2
), true, &pPoolItem
) == SfxItemState::SET
)
500 bFullSize
= static_cast<const SfxBoolItem
*>(pPoolItem
)->GetValue();
502 if(pMasterPage
->IsBackgroundFullSize() != bFullSize
)
503 bSetPageSizeAndBorder
= true;
507 if( pArgs
->GetItemState(mpDoc
->GetPool().GetWhich(SID_ATTR_PAGE_PAPERBIN
), true, &pPoolItem
) == SfxItemState::SET
)
509 nPaperBin
= static_cast<const SvxPaperBinItem
*>(pPoolItem
)->GetValue();
511 if( mpPage
->GetPaperBin() != nPaperBin
)
512 bSetPageSizeAndBorder
= true;
515 if (nLeft
== -1 && nUpper
!= -1)
517 bSetPageSizeAndBorder
= true;
518 nLeft
= mpPage
->GetLeftBorder();
519 nRight
= mpPage
->GetRightBorder();
521 else if (nLeft
!= -1 && nUpper
== -1)
523 bSetPageSizeAndBorder
= true;
524 nUpper
= mpPage
->GetUpperBorder();
525 nLower
= mpPage
->GetLowerBorder();
528 if( bSetPageSizeAndBorder
|| !mbMasterPage
)
529 mpDrawViewShell
->SetPageSizeAndBorder(ePageKind
, aNewSize
, nLeft
, nRight
, nUpper
, nLower
, bScaleAll
, eOrientation
, nPaperBin
, bFullSize
);
531 // if bMasterPage==sal_False then create a background-object for this page with the
532 // properties set in the dialog before, but if mbPageBckgrdDeleted==sal_True then
533 // the background of this page was set to invisible, so it would be a mistake
534 // to create a new background-object for this page !
536 if( mbDisplayBackgroundTabPage
)
538 if( !mbMasterPage
&& !mbPageBckgrdDeleted
)
541 mpBackgroundObjUndoAction
.reset( new SdBackgroundObjUndoAction(
542 *mpDoc
, *mpPage
, mpPage
->getSdrPageProperties().GetItemSet()) );
543 SfxItemSet
aSet( *pArgs
);
544 sdr::properties::CleanupFillProperties(aSet
);
545 mpPage
->getSdrPageProperties().ClearItem();
546 mpPage
->getSdrPageProperties().PutItemSet(aSet
);
550 // add undo action for background object
551 if( mpBackgroundObjUndoAction
)
553 // set merge flag, because a SdUndoGroupAction could have been inserted before
554 mpDocSh
->GetUndoManager()->AddUndoAction( mpBackgroundObjUndoAction
.release(), true );
557 // Objects can not be bigger than ViewSize
558 Size aPageSize
= mpDoc
->GetSdPage(0, ePageKind
)->GetSize();
559 Size
aViewSize(aPageSize
.Width() * 3, aPageSize
.Height() * 2);
560 mpDoc
->SetMaxObjSize(aViewSize
);
562 // if necessary, we tell Preview the new context
563 mpDrawViewShell
->UpdatePreview( mpDrawViewShell
->GetActualPage() );
566 } // end of namespace sd
568 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */