Get the style color and number just once
[LibreOffice.git] / sd / source / ui / func / futempl.cxx
blob07580a6cef03a06bb829198e9bb68afe52756ac9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
21 #include <com/sun/star/beans/XPropertySet.hpp>
22 #include <com/sun/star/container/XNameAccess.hpp>
23 #include <com/sun/star/frame/XModel.hpp>
25 #include <futempl.hxx>
27 #include <svx/svxids.hrc>
28 #include <sfx2/bindings.hxx>
29 #include <sfx2/dispatch.hxx>
30 #include <editeng/eeitem.hxx>
31 #include <sfx2/request.hxx>
32 #include <sfx2/sfxdlg.hxx>
33 #include <editeng/numitem.hxx>
34 #include <svx/svdopage.hxx>
35 #include <editeng/colritem.hxx>
36 #include <editeng/brushitem.hxx>
37 #include <svx/svditer.hxx>
38 #include <svx/sdr/properties/properties.hxx>
39 #include <svl/intitem.hxx>
41 #include <sfx2/viewfrm.hxx>
42 #include <svx/xlndsit.hxx>
43 #include <svx/xlnstit.hxx>
44 #include <svx/xlnedit.hxx>
45 #include <svx/xbtmpit.hxx>
46 #include <svx/xflgrit.hxx>
47 #include <svx/xflftrit.hxx>
48 #include <svx/xflhtit.hxx>
49 #include <o3tl/string_view.hxx>
50 #include <app.hrc>
51 #include <stlsheet.hxx>
52 #include <sdpage.hxx>
53 #include <stlpool.hxx>
54 #include <sdmod.hxx>
55 #include <View.hxx>
56 #include <drawdoc.hxx>
57 #include <DrawDocShell.hxx>
58 #include <DrawViewShell.hxx>
59 #include <ViewShell.hxx>
61 #include <strings.hrc>
62 #include <prlayout.hxx>
63 #include <sdresid.hxx>
64 #include <OutlineView.hxx>
65 #include <sdabstdlg.hxx>
66 #include <memory>
68 using namespace com::sun::star::uno;
69 using namespace com::sun::star::container;
70 using namespace com::sun::star::beans;
71 using namespace com::sun::star::style;
73 namespace sd
77 FuTemplate::FuTemplate (
78 ViewShell* pViewSh,
79 ::sd::Window* pWin,
80 ::sd::View* pView,
81 SdDrawDocument* pDoc,
82 SfxRequest& rReq )
83 : FuPoor( pViewSh, pWin, pView, pDoc, rReq )
87 rtl::Reference<FuPoor> FuTemplate::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
89 rtl::Reference<FuPoor> xFunc( new FuTemplate( pViewSh, pWin, pView, pDoc, rReq ) );
90 xFunc->DoExecute(rReq);
91 return xFunc;
94 void FuTemplate::DoExecute( SfxRequest& rReq )
96 const SfxItemSet* pArgs = rReq.GetArgs();
97 sal_uInt16 nSId = rReq.GetSlot();
99 // get StyleSheet parameter
100 SfxStyleSheetBasePool* pSSPool = mpDoc->GetDocSh()->GetStyleSheetPool();
101 SfxStyleSheetBase* pStyleSheet = nullptr;
103 const SfxPoolItem* pItem;
104 SfxStyleFamily nFamily = SfxStyleFamily(USHRT_MAX);
105 if( pArgs && SfxItemState::SET == pArgs->GetItemState( SID_STYLE_FAMILY,
106 false, &pItem ))
108 nFamily = static_cast<SfxStyleFamily>( pArgs->Get( SID_STYLE_FAMILY ).GetValue());
110 else if( pArgs && SfxItemState::SET == pArgs->GetItemState( SID_STYLE_FAMILYNAME,
111 false, &pItem ))
113 OUString sFamily = pArgs->Get( SID_STYLE_FAMILYNAME ).GetValue();
114 if (sFamily == "graphics")
115 nFamily = SfxStyleFamily::Para;
116 else
117 nFamily = SfxStyleFamily::Pseudo;
120 OUString aStyleName;
121 sal_uInt16 nRetMask = static_cast<sal_uInt16>(SfxStyleSearchBits::All);
123 switch( nSId )
125 case SID_STYLE_APPLY:
126 case SID_STYLE_EDIT:
127 case SID_STYLE_DELETE:
128 case SID_STYLE_HIDE:
129 case SID_STYLE_SHOW:
130 case SID_STYLE_FAMILY:
131 case SID_STYLE_NEW_BY_EXAMPLE:
133 const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(SID_APPLY_STYLE);
134 const SfxStringItem* pFamilyItem = rReq.GetArg<SfxStringItem>(SID_STYLE_FAMILYNAME);
135 if ( pFamilyItem && pNameItem )
139 Reference< XStyleFamiliesSupplier > xModel(mpDoc->GetDocSh()->GetModel(), UNO_QUERY_THROW );
140 Reference< XNameAccess > xCont( xModel->getStyleFamilies() );
141 Reference< XNameAccess > xStyles( xCont->getByName(pFamilyItem->GetValue()), UNO_QUERY_THROW );
142 Reference< XPropertySet > xInfo( xStyles->getByName( pNameItem->GetValue() ), UNO_QUERY_THROW );
144 OUString aUIName;
145 xInfo->getPropertyValue( u"DisplayName"_ustr ) >>= aUIName;
146 if ( !aUIName.isEmpty() )
147 rReq.AppendItem( SfxStringItem( nSId, aUIName ) );
149 catch( Exception& )
154 if (pArgs && pArgs->GetItemState(nSId) == SfxItemState::SET)
155 aStyleName = static_cast<const SfxStringItem &>( pArgs->Get( nSId ) ).GetValue();
159 switch( nSId )
161 case SID_STYLE_NEW:
163 SfxStyleSheetBase *p = pSSPool->Find(aStyleName, nFamily );
164 if(p)
166 pSSPool->Remove(p);
167 p = nullptr;
169 pStyleSheet = &pSSPool->Make( aStyleName, nFamily, SfxStyleSearchBits::UserDefined );
171 if (pArgs && pArgs->GetItemState(SID_STYLE_REFERENCE) == SfxItemState::SET)
173 OUString aParentName( pArgs->Get(SID_STYLE_REFERENCE).GetValue());
174 pStyleSheet->SetParent(aParentName);
176 else
178 pStyleSheet->SetParent(SdResId(STR_STANDARD_STYLESHEET_NAME));
181 break;
183 case SID_STYLE_NEW_BY_EXAMPLE:
185 // at the moment, the dialog to enter the name of the template is still opened
186 SfxStyleSheetBase *p = pSSPool->Find(aStyleName, nFamily );
187 if(p)
189 pSSPool->Remove(p);
190 p = nullptr;
192 pStyleSheet = &pSSPool->Make( aStyleName, nFamily, SfxStyleSearchBits::UserDefined );
193 pStyleSheet->SetParent(SdResId(STR_STANDARD_STYLESHEET_NAME));
195 break;
197 case SID_STYLE_EDIT:
198 pStyleSheet = pSSPool->Find( aStyleName, nFamily);
199 break;
201 case SID_STYLE_DELETE:
202 pStyleSheet = pSSPool->Find( aStyleName, nFamily);
203 if( pStyleSheet )
205 pSSPool->Remove( pStyleSheet );
206 nRetMask = sal_uInt16(true);
207 mpDoc->SetChanged();
209 else
211 nRetMask = sal_uInt16(false);
213 break;
215 case SID_STYLE_HIDE:
216 case SID_STYLE_SHOW:
217 pStyleSheet = pSSPool->Find( aStyleName, nFamily);
218 pStyleSheet->SetHidden( nSId == SID_STYLE_HIDE );
219 nRetMask = sal_uInt16(true);
220 break;
222 case SID_STYLE_APPLY:
223 // apply the template to the document
224 pStyleSheet = pSSPool->Find( aStyleName, nFamily);
226 // do not set presentation styles, they will be set implicit
227 if ( pStyleSheet && pStyleSheet->GetFamily() != SfxStyleFamily::Pseudo )
229 SfxStyleSheet* pOldStyleSheet = mpView->GetStyleSheet();
230 OUString aStr;
232 if( // if the object had no style sheet, allow all
233 !pOldStyleSheet ||
235 // allow if old and new style sheet has same family
236 pStyleSheet->GetFamily() == pOldStyleSheet->GetFamily() ||
238 // allow if old was background objects and new is graphics
239 (pStyleSheet->GetFamily() == SfxStyleFamily::Para && pOldStyleSheet->GetHelpId( aStr ) == HID_PSEUDOSHEET_BACKGROUNDOBJECTS) ||
241 // allow if old was presentation and we are a drawing document
242 (pOldStyleSheet->GetFamily() == SfxStyleFamily::Page && mpDoc->GetDocumentType() == DocumentType::Draw) )
244 mpView->SetStyleSheet( static_cast<SfxStyleSheet*>(pStyleSheet));
245 mpDoc->SetChanged();
246 mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_STYLE_FAMILY2 );
249 break;
251 case SID_STYLE_WATERCAN:
253 if (SdModule* mod = SdModule::get(); !mod->GetWaterCan())
255 if (pArgs && pArgs->GetItemState( nSId ) == SfxItemState::SET)
257 aStyleName = static_cast<const SfxStringItem &>( pArgs->Get( nSId ) ).GetValue();
258 mod->SetWaterCan(true);
259 pStyleSheet = pSSPool->Find( aStyleName, nFamily);
261 // no presentation object templates, they are only allowed implicitly
262 if( pStyleSheet && pStyleSheet->GetFamily() != SfxStyleFamily::Pseudo )
264 static_cast<SdStyleSheetPool*>( pSSPool )->SetActualStyleSheet( pStyleSheet );
266 // we switch explicitly into selection mode
267 mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_OBJECT_SELECT,
268 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
271 else
272 mod->SetWaterCan(false);
274 else
276 mod->SetWaterCan(false);
277 // we have to re-enable to tools-bar
278 mpViewShell->Invalidate();
281 break;
283 default:
284 break;
287 switch( nSId )
289 case SID_STYLE_NEW:
290 case SID_STYLE_EDIT:
292 PresentationObjects ePO = PresentationObjects::Outline_1;
294 if( pStyleSheet )
296 ScopedVclPtr<SfxAbstractTabDialog> pStdDlg;
297 ScopedVclPtr<SfxAbstractTabDialog> pPresDlg;
298 SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
300 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
302 if (eFamily == SfxStyleFamily::Para)
304 pStdDlg.disposeAndReset(pFact ? pFact->CreateSdTabTemplateDlg(mpViewShell->GetFrameWeld(), mpDoc->GetDocSh(), *pStyleSheet, mpDoc, mpView) : nullptr);
306 else if (eFamily == SfxStyleFamily::Pseudo)
308 OUString aName(pStyleSheet->GetName());
309 bool bBackground = false;
310 bool bOldDocInOtherLanguage = false;
312 if (aName == SdResId(STR_PSEUDOSHEET_TITLE))
314 ePO = PresentationObjects::Title;
316 else if (aName == SdResId(STR_PSEUDOSHEET_SUBTITLE))
318 ePO = PresentationObjects::Subtitle;
320 else if (aName ==
321 SdResId(STR_PSEUDOSHEET_BACKGROUND))
323 bBackground = true;
324 ePO = PresentationObjects::Background;
326 else if (aName ==
327 SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS))
329 ePO = PresentationObjects::BackgroundObjects;
331 else if (aName ==
332 SdResId(STR_PSEUDOSHEET_NOTES))
334 ePO = PresentationObjects::Notes;
336 else if(aName.indexOf(SdResId(STR_PSEUDOSHEET_OUTLINE)) != -1)
338 OUString aOutlineStr(SdResId(STR_PSEUDOSHEET_OUTLINE));
339 // determine number, mind the blank between name and number
340 std::u16string_view aNumStr(aName.subView(aOutlineStr.getLength() + 1));
341 sal_uInt16 nLevel = static_cast<sal_uInt16>(o3tl::toInt32(aNumStr));
342 switch (nLevel)
344 case 1: ePO = PresentationObjects::Outline_1; break;
345 case 2: ePO = PresentationObjects::Outline_2; break;
346 case 3: ePO = PresentationObjects::Outline_3; break;
347 case 4: ePO = PresentationObjects::Outline_4; break;
348 case 5: ePO = PresentationObjects::Outline_5; break;
349 case 6: ePO = PresentationObjects::Outline_6; break;
350 case 7: ePO = PresentationObjects::Outline_7; break;
351 case 8: ePO = PresentationObjects::Outline_8; break;
352 case 9: ePO = PresentationObjects::Outline_9; break;
355 else
357 OSL_FAIL("StyleSheet from older version with different language");
358 bOldDocInOtherLanguage = true;
361 if( !bOldDocInOtherLanguage )
363 pPresDlg.disposeAndReset(pFact ? pFact->CreateSdPresLayoutTemplateDlg(mpDocSh, mpViewShell->GetFrameWeld(), bBackground, *pStyleSheet, ePO, pSSPool ) : nullptr);
367 sal_uInt16 nResult = RET_CANCEL;
368 const SfxItemSet* pOutSet = nullptr;
369 if (pStdDlg)
371 nResult = pStdDlg->Execute();
372 pOutSet = pStdDlg->GetOutputItemSet();
374 else if( pPresDlg )
376 nResult = pPresDlg->Execute();
377 pOutSet = pPresDlg->GetOutputItemSet();
380 switch( nResult )
382 case RET_OK:
384 nRetMask = static_cast<sal_uInt16>(pStyleSheet->GetMask());
386 if (eFamily == SfxStyleFamily::Pseudo)
388 SfxItemSet aTempSet(*pOutSet);
389 /* Extract SvxBrushItem out of set and insert SvxColorItem */
390 const SvxBrushItem* pBrushItem = aTempSet.GetItem<SvxBrushItem>( SID_ATTR_BRUSH_CHAR );
392 if ( pBrushItem )
394 SvxColorItem aBackColorItem(pBrushItem->GetColor(), EE_CHAR_BKGCOLOR);
395 aTempSet.ClearItem( EE_CHAR_BKGCOLOR );
396 aTempSet.Put( aBackColorItem );
398 static_cast<SdStyleSheet*>(pStyleSheet)->AdjustToFontHeight(aTempSet);
400 /* Special treatment: reset the INVALIDS to
401 NULL-Pointer (otherwise INVALIDs or pointer point
402 to DefaultItems in the template; both would
403 prevent the attribute inheritance) */
404 aTempSet.ClearInvalidItems();
406 // EE_PARA_NUMBULLET item is only valid in first outline template
407 if( (ePO >= PresentationObjects::Outline_2) && (ePO <= PresentationObjects::Outline_9) )
409 const SvxNumBulletItem* pBulletItem = nullptr;
410 if (aTempSet.GetItemState(EE_PARA_NUMBULLET, true, &pBulletItem) == SfxItemState::SET)
412 SvxNumRule aRule(pBulletItem->GetNumRule());
414 OUString sStyleName(SdResId(STR_PSEUDOSHEET_OUTLINE) + " 1");
415 SfxStyleSheetBase* pFirstStyleSheet = pSSPool->Find( sStyleName, SfxStyleFamily::Pseudo);
417 if(pFirstStyleSheet)
419 pFirstStyleSheet->GetItemSet().Put( SvxNumBulletItem( aRule, EE_PARA_NUMBULLET ));
420 SdStyleSheet* pRealSheet = static_cast<SdStyleSheet*>(pFirstStyleSheet)->GetRealStyleSheet();
421 pRealSheet->Broadcast(SfxHint(SfxHintId::DataChanged));
424 aTempSet.ClearItem( EE_PARA_NUMBULLET );
428 pStyleSheet->GetItemSet().Put(aTempSet);
429 SdStyleSheet::BroadcastSdStyleSheetChange(pStyleSheet, ePO, pSSPool);
432 SfxItemSet& rAttr = pStyleSheet->GetItemSet();
434 sdr::properties::CleanupFillProperties( rAttr );
436 // check for unique names of named items for xml
437 const SfxPoolItem* pOldItem = nullptr;
438 if( rAttr.GetItemState( XATTR_FILLBITMAP, true, &pOldItem ) == SfxItemState::SET )
440 std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XFillBitmapItem*>(pOldItem)->checkForUniqueItem( *mpDoc );
441 if( pNewItem )
443 rAttr.Put( std::move(pNewItem) );
446 if( rAttr.GetItemState( XATTR_LINEDASH, true, &pOldItem ) == SfxItemState::SET )
448 std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XLineDashItem*>(pOldItem)->checkForUniqueItem( *mpDoc );
449 if( pNewItem )
451 rAttr.Put( std::move(pNewItem) );
454 if( rAttr.GetItemState( XATTR_LINESTART, true, &pOldItem ) == SfxItemState::SET )
456 std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XLineStartItem*>(pOldItem)->checkForUniqueItem( *mpDoc );
457 if( pNewItem )
459 rAttr.Put( std::move(pNewItem) );
462 if( rAttr.GetItemState( XATTR_LINEEND, true, &pOldItem ) == SfxItemState::SET )
464 std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XLineEndItem*>(pOldItem)->checkForUniqueItem( *mpDoc );
465 if( pNewItem )
467 rAttr.Put( std::move(pNewItem) );
470 if( rAttr.GetItemState( XATTR_FILLGRADIENT, true, &pOldItem ) == SfxItemState::SET )
472 std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XFillGradientItem*>(pOldItem)->checkForUniqueItem( *mpDoc );
473 if( pNewItem )
475 rAttr.Put( std::move(pNewItem) );
478 if( rAttr.GetItemState( XATTR_FILLFLOATTRANSPARENCE, true, &pOldItem ) == SfxItemState::SET )
480 std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XFillFloatTransparenceItem*>(pOldItem)->checkForUniqueItem( *mpDoc );
481 if( pNewItem )
483 rAttr.Put( std::move(pNewItem) );
486 if( rAttr.GetItemState( XATTR_FILLHATCH, true, &pOldItem ) == SfxItemState::SET )
488 std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XFillHatchItem*>(pOldItem)->checkForUniqueItem( *mpDoc );
489 if( pNewItem )
491 rAttr.Put( std::move(pNewItem) );
495 static_cast<SfxStyleSheet*>( pStyleSheet )->Broadcast( SfxHint( SfxHintId::DataChanged ) );
497 DrawViewShell* pDrawViewShell = dynamic_cast< DrawViewShell* >( mpViewShell );
498 if( pDrawViewShell )
500 PageKind ePageKind = pDrawViewShell->GetPageKind();
501 if( ePageKind == PageKind::Notes || ePageKind == PageKind::Handout )
503 SdPage* pPage = mpViewShell->GetActualPage();
505 if(pDrawViewShell->GetEditMode() == EditMode::MasterPage)
507 pPage = static_cast<SdPage*>((&(pPage->TRG_GetMasterPage())));
510 if( pPage )
512 SdrObjListIter aIter( pPage );
513 while( aIter.IsMore() )
515 SdrObject* pObj = aIter.Next();
516 if( dynamic_cast< const SdrPageObj *>( pObj ) != nullptr )
518 // repaint only
519 pObj->ActionChanged();
520 // pObj->SendRepaintBroadcast();
527 if( mpDoc->GetOnlineSpell() )
529 if( SfxItemState::SET == rAttr.GetItemState(EE_CHAR_LANGUAGE, false ) ||
530 SfxItemState::SET == rAttr.GetItemState(EE_CHAR_LANGUAGE_CJK, false ) ||
531 SfxItemState::SET == rAttr.GetItemState(EE_CHAR_LANGUAGE_CTL, false ) )
533 mpDoc->StopOnlineSpelling();
534 mpDoc->StartOnlineSpelling();
538 mpDoc->SetChanged();
540 break;
542 default:
544 if( nSId == SID_STYLE_NEW )
545 pSSPool->Remove( pStyleSheet );
547 return; // Cancel
551 break;
553 case SID_STYLE_NEW_BY_EXAMPLE:
555 if( pStyleSheet )
557 nRetMask = static_cast<sal_uInt16>(pStyleSheet->GetMask());
558 SfxItemSet aCoreSet( mpDoc->GetPool() );
559 mpView->GetAttributes( aCoreSet, true );
561 // if the object had a template, this becomes parent of the new template
562 SfxStyleSheet* pOldStyle = mpView->GetStyleSheet();
564 // if pOldStyle == pStyleSheet -> recursion
565 if( pOldStyle != pStyleSheet )
567 if (pOldStyle)
569 pStyleSheet->SetParent(pOldStyle->GetName());
572 SfxItemSet* pStyleSet = &pStyleSheet->GetItemSet();
573 pStyleSet->Put(aCoreSet);
575 /* apply template (but not when somebody is editing a text.
576 To do this, the edit engine had to be capable to use
577 templates on a character level. */
578 if (!mpView->GetTextEditObject())
580 mpView->SetStyleSheet( static_cast<SfxStyleSheet*>(pStyleSheet));
583 static_cast<SfxStyleSheet*>( pStyleSheet )->Broadcast( SfxHint( SfxHintId::DataChanged ) );
584 mpDoc->SetChanged();
586 mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_STYLE_FAMILY2 );
590 break;
592 case SID_STYLE_UPDATE_BY_EXAMPLE:
594 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
595 if ((rMarkList.GetMarkCount() != 0 && rMarkList.GetMarkCount() == 1) ||
596 dynamic_cast< const OutlineView *>( mpView ) != nullptr)
598 pStyleSheet = mpView->GetStyleSheet();
600 if( pStyleSheet )
602 nRetMask = static_cast<sal_uInt16>(pStyleSheet->GetMask());
603 SfxItemSet aCoreSet( mpDoc->GetPool() );
604 mpView->GetAttributes( aCoreSet );
606 SfxItemSet* pStyleSet = &pStyleSheet->GetItemSet();
607 pStyleSet->Put( aCoreSet );
609 mpView->SetStyleSheet( static_cast<SfxStyleSheet*>(pStyleSheet));
611 static_cast<SfxStyleSheet*>( pStyleSheet )->Broadcast( SfxHint( SfxHintId::DataChanged ) );
612 mpDoc->SetChanged();
613 mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_STYLE_FAMILY2 );
617 break;
620 if( nRetMask != static_cast<sal_uInt16>(SfxStyleSearchBits::All) )
621 rReq.SetReturnValue( SfxUInt16Item( nSId, nRetMask ) );
624 void FuTemplate::Activate()
628 void FuTemplate::Deactivate()
632 } // end of namespace sd
634 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */