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 .
23 #include <string_view>
25 #include <sfx2/tabdlg.hxx>
26 #include <sfx2/app.hxx>
27 #include <sfx2/sfxresid.hxx>
28 #include <sfx2/sfxdlg.hxx>
29 #include <sfx2/viewsh.hxx>
30 #include <unotools/viewoptions.hxx>
32 #include <vcl/virdev.hxx>
33 #include <sal/log.hxx>
34 #include <tools/debug.hxx>
35 #include <comphelper/lok.hxx>
37 #include <sfx2/strings.hrc>
40 using namespace ::com::sun::star::uno
;
42 constexpr OUStringLiteral USERITEM_NAME
= u
"UserItem";
48 SfxOkDialogController
* mpSfxDialogController
;
49 css::uno::Reference
< css::frame::XFrame
> mxFrame
;
51 TabPageImpl() : mbStandard(false), mpSfxDialogController(nullptr) {}
58 OUString sId
; // The ID
59 CreateTabPage fnCreatePage
; // Pointer to Factory
60 GetTabPageRanges fnGetRanges
; // Pointer to Ranges-Function
61 std::unique_ptr
<SfxTabPage
> xTabPage
; // The TabPage itself
62 bool bRefresh
; // Flag: Page must be re-initialized
65 Data_Impl( const OUString
& rId
, CreateTabPage fnPage
,
66 GetTabPageRanges fnRanges
) :
69 fnCreatePage( fnPage
),
70 fnGetRanges ( fnRanges
),
78 SfxTabDialogItem::SfxTabDialogItem( const SfxTabDialogItem
& rAttr
, SfxItemPool
* pItemPool
)
79 : SfxSetItem( rAttr
, pItemPool
)
83 SfxTabDialogItem::SfxTabDialogItem( sal_uInt16 nId
, const SfxItemSet
& rItemSet
)
84 : SfxSetItem( nId
, rItemSet
)
88 SfxTabDialogItem
* SfxTabDialogItem::Clone(SfxItemPool
* pToPool
) const
90 return new SfxTabDialogItem( *this, pToPool
);
93 typedef std::vector
<Data_Impl
*> SfxTabDlgData_Impl
;
97 bool bHideResetBtn
: 1;
99 SfxTabDlgData_Impl aData
;
101 explicit TabDlg_Impl(sal_uInt8 nCnt
)
102 : bHideResetBtn(false)
105 aData
.reserve( nCnt
);
109 static Data_Impl
* Find( const SfxTabDlgData_Impl
& rArr
, std::u16string_view rId
, sal_uInt16
* pPos
= nullptr)
111 const sal_uInt16 nCount
= rArr
.size();
113 for ( sal_uInt16 i
= 0; i
< nCount
; ++i
)
115 Data_Impl
* pObj
= rArr
[i
];
117 if ( pObj
->sId
== rId
)
127 void SfxTabPage::SetFrame(const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
130 mpImpl
->mxFrame
= xFrame
;
133 css::uno::Reference
< css::frame::XFrame
> SfxTabPage::GetFrame() const
136 return mpImpl
->mxFrame
;
137 return css::uno::Reference
< css::frame::XFrame
>();
140 SfxTabPage::SfxTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const OUString
& rUIXMLDescription
, const OUString
& rID
, const SfxItemSet
*rAttrSet
)
141 : BuilderPage(pPage
, pController
, rUIXMLDescription
, rID
,
142 comphelper::LibreOfficeKit::isActive() && SfxViewShell::Current()
143 && SfxViewShell::Current()->isLOKMobilePhone())
145 , mbHasExchangeSupport(false)
146 , mpImpl(new TabPageImpl
)
148 mpImpl
->mpSfxDialogController
= dynamic_cast<SfxOkDialogController
*>(m_pDialogController
);
151 SfxTabPage::~SfxTabPage()
155 std::unique_ptr
<weld::Container
> xParent(m_xContainer
->weld_parent());
157 xParent
->move(m_xContainer
.get(), nullptr);
159 m_xContainer
.reset();
164 bool SfxTabPage::FillItemSet( SfxItemSet
* )
169 void SfxTabPage::Reset( const SfxItemSet
* )
173 bool SfxTabPage::DeferResetToFirstActivation() { return false; }
175 void SfxTabPage::ActivatePage( const SfxItemSet
& )
178 Default implementation of the virtual ActivatePage method. This method is
179 called when a page of dialogue supports the exchange of data between pages.
180 <SfxTabPage::DeactivatePage(SfxItemSet *)>
185 DeactivateRC
SfxTabPage::DeactivatePage( SfxItemSet
* )
189 Default implementation of the virtual DeactivatePage method. This method is
190 called by Sfx when leaving a page; the application can, through the return
191 value, control whether to leave the page. If the page is displayed through
192 bHasExchangeSupport which supports data exchange between pages, then a
193 pointer to the exchange set is passed as parameter. This takes on data for
194 the exchange, then the set is available as a parameter in
195 <SfxTabPage::ActivatePage(const SfxItemSet &)>.
199 DeactivateRC::LeavePage; Allow leaving the page
203 return DeactivateRC::LeavePage
;
207 void SfxTabPage::FillUserData()
211 Virtual method is called by the base class in the destructor to save
212 specific information of the TabPage in the ini-file. When overriding a
213 string must be compiled, which is then flushed with the <SetUserData()>.
220 bool SfxTabPage::IsReadOnly() const
226 const SfxPoolItem
* SfxTabPage::GetItem( const SfxItemSet
& rSet
, sal_uInt16 nSlot
, bool bDeep
)
230 static Method: hereby are the implementations of the TabPage code
235 const SfxItemPool
* pPool
= rSet
.GetPool();
236 sal_uInt16 nWh
= pPool
->GetWhich( nSlot
, bDeep
);
237 const SfxPoolItem
* pItem
= nullptr;
238 rSet
.GetItemState( nWh
, true, &pItem
);
240 if ( !pItem
&& nWh
!= nSlot
)
241 pItem
= &pPool
->GetDefaultItem( nWh
);
246 const SfxPoolItem
* SfxTabPage::GetOldItem( const SfxItemSet
& rSet
,
247 sal_uInt16 nSlot
, bool bDeep
)
251 This method returns an attribute for comparison of the old value.
255 const SfxItemSet
& rOldSet
= GetItemSet();
256 sal_uInt16 nWh
= GetWhich( nSlot
, bDeep
);
257 const SfxPoolItem
* pItem
= nullptr;
259 if (mpImpl
->mbStandard
&& rOldSet
.GetParent())
260 pItem
= GetItem( *rOldSet
.GetParent(), nSlot
);
261 else if ( rSet
.GetParent() &&
262 SfxItemState::DONTCARE
== rSet
.GetItemState( nWh
) )
263 pItem
= GetItem( *rSet
.GetParent(), nSlot
);
265 pItem
= GetItem( rOldSet
, nSlot
);
269 void SfxTabPage::PageCreated( const SfxAllItemSet
& /*aSet*/ )
271 SAL_WARN( "sfx.dialog", "SfxTabPage::PageCreated should not be called");
274 void SfxTabPage::ChangesApplied()
278 void SfxTabPage::SetDialogController(SfxOkDialogController
* pDialog
)
280 mpImpl
->mpSfxDialogController
= pDialog
;
281 m_pDialogController
= mpImpl
->mpSfxDialogController
;
284 SfxOkDialogController
* SfxTabPage::GetDialogController() const
286 return mpImpl
->mpSfxDialogController
;
289 OUString
SfxTabPage::GetHelpId() const
292 return m_xContainer
->get_help_id();
296 weld::Window
* SfxTabPage::GetFrameWeld() const
298 if (m_pDialogController
)
299 return m_pDialogController
->getDialog();
303 const SfxItemSet
* SfxTabPage::GetDialogExampleSet() const
305 if (mpImpl
->mpSfxDialogController
)
306 return mpImpl
->mpSfxDialogController
->GetExampleSet();
310 SfxTabDialogController::SfxTabDialogController
312 weld::Widget
* pParent
, // Parent Window
313 const OUString
& rUIXMLDescription
, const OUString
& rID
, // Dialog .ui path, Dialog Name
314 const SfxItemSet
* pItemSet
, // Itemset with the data;
315 // can be NULL, when Pages are onDemand
316 bool bEditFmt
// when yes -> additional Button for standard
318 : SfxOkDialogController(pParent
, rUIXMLDescription
, rID
)
319 , m_xTabCtrl(m_xBuilder
->weld_notebook("tabcontrol"))
320 , m_xOKBtn(m_xBuilder
->weld_button("ok"))
321 , m_xApplyBtn(m_xBuilder
->weld_button("apply"))
322 , m_xUserBtn(m_xBuilder
->weld_button("user"))
323 , m_xCancelBtn(m_xBuilder
->weld_button("cancel"))
324 , m_xResetBtn(m_xBuilder
->weld_button("reset"))
325 , m_xBaseFmtBtn(m_xBuilder
->weld_button("standard"))
326 , m_pSet(pItemSet
? new SfxItemSet(*pItemSet
) : nullptr)
327 , m_bStandardPushed(false)
329 m_pImpl
.reset(new TabDlg_Impl(m_xTabCtrl
->get_n_pages()));
330 m_pImpl
->bHideResetBtn
= !m_xResetBtn
->get_visible();
331 m_xOKBtn
->connect_clicked(LINK(this, SfxTabDialogController
, OkHdl
));
332 m_xCancelBtn
->connect_clicked(LINK(this, SfxTabDialogController
, CancelHdl
));
333 m_xResetBtn
->connect_clicked(LINK(this, SfxTabDialogController
, ResetHdl
));
334 m_xResetBtn
->set_label(SfxResId(STR_RESET
));
335 m_xTabCtrl
->connect_enter_page(LINK(this, SfxTabDialogController
, ActivatePageHdl
));
336 m_xTabCtrl
->connect_leave_page(LINK(this, SfxTabDialogController
, DeactivatePageHdl
));
337 m_xResetBtn
->set_help_id(HID_TABDLG_RESET_BTN
);
341 m_xBaseFmtBtn
->set_label(SfxResId(STR_STANDARD_SHORTCUT
));
342 m_xBaseFmtBtn
->connect_clicked(LINK(this, SfxTabDialogController
, BaseFmtHdl
));
343 m_xBaseFmtBtn
->set_help_id(HID_TABDLG_STANDARD_BTN
);
344 m_xBaseFmtBtn
->show();
348 m_xUserBtn
->connect_clicked(LINK(this, SfxTabDialogController
, UserHdl
));
352 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
353 m_pOutSet
.reset(new SfxItemSet(*m_pSet
->GetPool(), m_pSet
->GetRanges()));
356 // The reset functionality seems to be confusing to many; disable in LOK.
357 if (comphelper::LibreOfficeKit::isActive())
361 IMPL_LINK_NOARG(SfxTabDialogController
, OkHdl
, weld::Button
&, void)
365 Handler of the Ok-Buttons
366 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
367 Returns <DeactivateRC::LeavePage>, <SfxTabDialog::Ok()> is called
368 and the Dialog is ended.
372 if (PrepareLeaveCurrentPage())
373 m_xDialog
->response(Ok());
376 IMPL_LINK_NOARG(SfxTabDialogController
, UserHdl
, weld::Button
&, void)
380 Handler of the User-Buttons
381 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
382 returns this <DeactivateRC::LeavePage> and <SfxTabDialog::Ok()> is called.
383 Then the Dialog is ended with the Return value <SfxTabDialog::Ok()>
387 if (PrepareLeaveCurrentPage())
394 m_xDialog
->response(nRet
);
398 IMPL_LINK_NOARG(SfxTabDialogController
, CancelHdl
, weld::Button
&, void)
400 m_xDialog
->response(RET_CANCEL
);
403 IMPL_LINK_NOARG(SfxTabDialogController
, ResetHdl
, weld::Button
&, void)
407 Handler behind the reset button.
408 The Current Page is new initialized with their initial data, all the
409 settings that the user has made on this page are repealed.
413 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, m_xTabCtrl
->get_current_page_ident());
414 assert(pDataObject
&& "Id not known");
416 pDataObject
->xTabPage
->Reset(m_pSet
.get());
417 // Also reset relevant items of ExampleSet and OutSet to initial state
418 if (!pDataObject
->fnGetRanges
)
422 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
424 const SfxItemPool
* pPool
= m_pSet
->GetPool();
425 const WhichRangesContainer
& pTmpRanges
= (pDataObject
->fnGetRanges
)();
427 for (const auto & rPair
: pTmpRanges
)
429 // Correct Range with multiple values
430 sal_uInt16 nTmp
= rPair
.first
, nTmpEnd
= rPair
.second
;
431 DBG_ASSERT(nTmp
<= nTmpEnd
, "Range is sorted the wrong way");
435 // If really sorted wrongly, then set new
436 std::swap(nTmp
, nTmpEnd
);
439 while (nTmp
&& nTmp
<= nTmpEnd
)
441 // Iterate over the Range and set the Items
442 sal_uInt16 nWh
= pPool
->GetWhich(nTmp
);
443 const SfxPoolItem
* pItem
;
444 if (SfxItemState::SET
== m_pSet
->GetItemState(nWh
, false, &pItem
))
446 m_xExampleSet
->Put(*pItem
);
447 m_pOutSet
->Put(*pItem
);
451 m_xExampleSet
->ClearItem(nWh
);
452 m_pOutSet
->ClearItem(nWh
);
461 Handler behind the Standard-Button.
462 This button is available when editing style sheets. All the set attributes
463 in the edited stylesheet are deleted.
465 IMPL_LINK_NOARG(SfxTabDialogController
, BaseFmtHdl
, weld::Button
&, void)
467 m_bStandardPushed
= true;
469 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, m_xTabCtrl
->get_current_page_ident());
470 assert(pDataObject
&& "Id not known");
472 if (!pDataObject
->fnGetRanges
)
476 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
478 const SfxItemPool
* pPool
= m_pSet
->GetPool();
479 const WhichRangesContainer
& pTmpRanges
= (pDataObject
->fnGetRanges
)();
480 SfxItemSet
aTmpSet(*m_xExampleSet
);
482 for (const auto& rPair
: pTmpRanges
)
484 // Correct Range with multiple values
485 sal_uInt16 nTmp
= rPair
.first
, nTmpEnd
= rPair
.second
;
486 DBG_ASSERT( nTmp
<= nTmpEnd
, "Range is sorted the wrong way" );
488 if ( nTmp
> nTmpEnd
)
490 // If really sorted wrongly, then set new
491 std::swap(nTmp
, nTmpEnd
);
494 while ( nTmp
&& nTmp
<= nTmpEnd
) // guard against overflow
496 // Iterate over the Range and set the Items
497 sal_uInt16 nWh
= pPool
->GetWhich(nTmp
);
498 m_xExampleSet
->ClearItem(nWh
);
499 aTmpSet
.ClearItem(nWh
);
500 // At the Outset of InvalidateItem,
501 // so that the change takes effect
502 m_pOutSet
->InvalidateItem(nWh
);
506 // Set all Items as new -> the call the current Page Reset()
507 assert(pDataObject
->xTabPage
&& "the Page is gone");
508 pDataObject
->xTabPage
->Reset( &aTmpSet
);
509 pDataObject
->xTabPage
->mpImpl
->mbStandard
= true;
512 IMPL_LINK(SfxTabDialogController
, ActivatePageHdl
, const OUString
&, rPage
, void)
517 void SfxTabDialogController::ActivatePage(const OUString
& rPage
)
520 Handler that is called by StarView for switching to a different page.
521 If possible the <SfxTabPage::Reset(const SfxItemSet &)> or
522 <SfxTabPage::ActivatePage(const SfxItemSet &)> is called on the new page
526 assert(!m_pImpl
->aData
.empty() && "no Pages registered");
527 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, rPage
);
530 SAL_WARN("sfx.dialog", "Tab Page ID '" << rPage
<< "' not known, this is pretty serious and needs investigation");
534 SfxTabPage
* pTabPage
= pDataObject
->xTabPage
.get();
538 if (pDataObject
->bRefresh
)
539 pTabPage
->Reset(m_pSet
.get());
540 pDataObject
->bRefresh
= false;
543 pTabPage
->ActivatePage(*m_xExampleSet
);
545 if (pTabPage
->IsReadOnly() || m_pImpl
->bHideResetBtn
)
551 IMPL_LINK(SfxTabDialogController
, DeactivatePageHdl
, const OUString
&, rPage
, bool)
553 return DeactivatePage(rPage
);
556 bool SfxTabDialogController::DeactivatePage(std::u16string_view aPage
)
559 Handler that is called by StarView before leaving a page.
563 <SfxTabPage::DeactivatePage(SfxItemSet *)>
567 assert(!m_pImpl
->aData
.empty() && "no Pages registered");
568 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, aPage
);
571 SAL_WARN("sfx.dialog", "Tab Page ID not known, this is pretty serious and needs investigation");
575 SfxTabPage
* pPage
= pDataObject
->xTabPage
.get();
579 DeactivateRC nRet
= DeactivateRC::LeavePage
;
581 if (!m_xExampleSet
&& pPage
->HasExchangeSupport() && m_pSet
)
582 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
->GetPool(), m_pSet
->GetRanges()));
586 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
588 if (pPage
->HasExchangeSupport())
589 nRet
= pPage
->DeactivatePage(&aTmp
);
591 nRet
= pPage
->DeactivatePage(nullptr);
592 if ( ( DeactivateRC::LeavePage
& nRet
) == DeactivateRC::LeavePage
&&
593 aTmp
.Count() && m_xExampleSet
)
595 m_xExampleSet
->Put( aTmp
);
596 m_pOutSet
->Put( aTmp
);
601 if ( pPage
->HasExchangeSupport() ) //!!!
605 SfxItemPool
* pPool
= pPage
->GetItemSet().GetPool();
606 m_xExampleSet
.reset(new SfxItemSet(*pPool
, GetInputRanges(*pPool
)));
608 nRet
= pPage
->DeactivatePage(m_xExampleSet
.get());
611 nRet
= pPage
->DeactivatePage( nullptr );
614 if ( nRet
& DeactivateRC::RefreshSet
)
617 // Flag all Pages as to be initialized as new
619 for (auto const& elem
: m_pImpl
->aData
)
621 elem
->bRefresh
= ( elem
->xTabPage
.get() != pPage
); // Do not refresh own Page anymore
624 return static_cast<bool>(nRet
& DeactivateRC::LeavePage
);
627 bool SfxTabDialogController::PrepareLeaveCurrentPage()
629 const OUString sId
= m_xTabCtrl
->get_current_page_ident();
630 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, sId
);
631 DBG_ASSERT( pDataObject
, "Id not known" );
632 SfxTabPage
* pPage
= pDataObject
? pDataObject
->xTabPage
.get() : nullptr;
638 DeactivateRC nRet
= DeactivateRC::LeavePage
;
641 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
643 if ( pPage
->HasExchangeSupport() )
644 nRet
= pPage
->DeactivatePage( &aTmp
);
646 nRet
= pPage
->DeactivatePage( nullptr );
648 if ( ( DeactivateRC::LeavePage
& nRet
) == DeactivateRC::LeavePage
651 m_xExampleSet
->Put( aTmp
);
652 m_pOutSet
->Put( aTmp
);
656 nRet
= pPage
->DeactivatePage( nullptr );
657 bEnd
= nRet
!= DeactivateRC::KeepPage
;
663 const WhichRangesContainer
& SfxTabDialogController::GetInputRanges(const SfxItemPool
& rPool
)
667 Makes the set over the range of all pages of the dialogue. Pages have the
668 static method for querying their range in AddTabPage, ie deliver their
673 Pointer to a null-terminated array of sal_uInt16. This array belongs to the
674 dialog and is deleted when the dialogue is destroy.
678 <SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, bool)>
679 <SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)>
680 <SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)>
686 SAL_WARN( "sfx.dialog", "Set already exists!" );
687 return m_pSet
->GetRanges();
690 if ( !m_pRanges
.empty() )
692 SfxItemSet
aUS(const_cast<SfxItemPool
&>(rPool
));
694 for (auto const& elem
: m_pImpl
->aData
)
697 if ( elem
->fnGetRanges
)
699 const WhichRangesContainer
& pTmpRanges
= (elem
->fnGetRanges
)();
701 for (const auto & rPair
: pTmpRanges
)
703 sal_uInt16 nWidFrom
= rPool
.GetWhich(rPair
.first
);
704 sal_uInt16 nWidTo
= rPool
.GetWhich(rPair
.second
);
705 aUS
.MergeRange(nWidFrom
, nWidTo
); // Keep it valid
710 m_pRanges
= aUS
.GetRanges();
714 SfxTabDialogController::~SfxTabDialogController()
718 for (auto & elem
: m_pImpl
->aData
)
720 if ( elem
->xTabPage
)
722 // save settings of all pages (user data)
723 elem
->xTabPage
->FillUserData();
724 OUString
aPageData( elem
->xTabPage
->GetUserData() );
725 if ( !aPageData
.isEmpty() )
727 // save settings of all pages (user data)
728 SvtViewOptions
aPageOpt(EViewType::TabPage
, elem
->xTabPage
->GetConfigId());
729 aPageOpt
.SetUserItem( USERITEM_NAME
, Any( aPageData
) );
732 elem
->xTabPage
.reset();
739 short SfxTabDialogController::Ok()
743 Ok handler for the Dialogue.
745 Dialog's current location and current page are saved for the next time
748 The OutputSet is created and for each page this or the special OutputSet
749 is set by calling the method <SfxTabPage::FillItemSet(SfxItemSet &)>, to
750 insert the entered data by the user into the set.
754 RET_OK: if at least one page has returned from FillItemSet,
755 otherwise RET_CANCEL.
758 SavePosAndId(); //See fdo#38828 "Apply" resetting window position
763 m_pOutSet
.reset(new SfxItemSet( *m_xExampleSet
));
765 m_pOutSet
= m_pSet
->Clone( false ); // without Items
767 bool bModified
= false;
769 for (auto const& elem
: m_pImpl
->aData
)
771 SfxTabPage
* pTabPage
= elem
->xTabPage
.get();
775 if ( m_pSet
&& !pTabPage
->HasExchangeSupport() )
777 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
779 if ( pTabPage
->FillItemSet( &aTmp
) )
783 m_xExampleSet
->Put( aTmp
);
784 m_pOutSet
->Put( aTmp
);
790 if (m_pOutSet
&& m_pOutSet
->Count() > 0)
793 if (m_bStandardPushed
)
796 return bModified
? RET_OK
: RET_CANCEL
;
799 void SfxTabDialogController::RefreshInputSet()
803 Default implementation of the virtual Method.
804 This is called, when <SfxTabPage::DeactivatePage(SfxItemSet *)>
805 returns <DeactivateRC::RefreshSet>.
809 SAL_INFO ( "sfx.dialog", "RefreshInputSet not implemented" );
812 void SfxTabDialogController::PageCreated
816 Default implementation of the virtual method. This is called immediately
817 after creating a page. Here the dialogue can call the TabPage Method
822 const OUString
&, // Id of the created page
823 SfxTabPage
& // Reference to the created page
828 void SfxTabDialogController::SavePosAndId()
830 // save settings (screen position and current page)
831 SvtViewOptions
aDlgOpt(EViewType::TabDialog
, m_xDialog
->get_help_id());
832 aDlgOpt
.SetPageID(m_xTabCtrl
->get_current_page_ident());
836 Adds a page to the dialog. The Name must correspond to an entry in the
837 TabControl in the dialog .ui
839 void SfxTabDialogController::AddTabPage(const OUString
&rName
/* Page ID */,
840 CreateTabPage pCreateFunc
/* Pointer to the Factory Method */,
841 GetTabPageRanges pRangesFunc
/* Pointer to the Method for querying Ranges onDemand */)
843 m_pImpl
->aData
.push_back(new Data_Impl(rName
, pCreateFunc
, pRangesFunc
));
846 void SfxTabDialogController::AddTabPage(const OUString
&rName
/* Page ID */,
847 sal_uInt16 nPageCreateId
/* Identifier of the Factory Method to create the page */)
849 SfxAbstractDialogFactory
* pFact
= SfxAbstractDialogFactory::Create();
850 CreateTabPage pCreateFunc
= pFact
->GetTabPageCreatorFunc(nPageCreateId
);
851 GetTabPageRanges pRangesFunc
= pFact
->GetTabPageRangesFunc(nPageCreateId
);
852 AddTabPage(rName
, pCreateFunc
, pRangesFunc
);
857 Add a page to the dialog. The Rider text is passed on, the page has no
858 counterpart in the TabControl in the resource of the dialogue.
861 void SfxTabDialogController::AddTabPage(const OUString
&rName
, /* Page ID */
862 const OUString
& rRiderText
,
863 CreateTabPage pCreateFunc
/* Pointer to the Factory Method */)
865 assert(!m_xTabCtrl
->get_page(rName
) && "Double Page-Ids in the Tabpage");
866 m_xTabCtrl
->append_page(rName
, rRiderText
);
867 AddTabPage(rName
, pCreateFunc
, nullptr);
870 void SfxTabDialogController::AddTabPage(const OUString
&rName
, const OUString
& rRiderText
,
871 sal_uInt16 nPageCreateId
/* Identifier of the Factory Method to create the page */)
873 assert(!m_xTabCtrl
->get_page(rName
) && "Double Page-Ids in the Tabpage");
874 m_xTabCtrl
->append_page(rName
, rRiderText
);
875 AddTabPage(rName
, nPageCreateId
);
880 Default implementation of the virtual Method.
881 This is called when pages create their sets onDemand.
883 SfxItemSet
* SfxTabDialogController::CreateInputItemSet(const OUString
&)
885 SAL_WARN( "sfx.dialog", "CreateInputItemSet not implemented" );
886 m_xItemSet
= std::make_unique
<SfxAllItemSet
>(SfxGetpApp()->GetPool());
887 return m_xItemSet
.get();
890 void SfxTabDialogController::CreatePages()
892 for (auto pDataObject
: m_pImpl
->aData
)
894 if (pDataObject
->xTabPage
)
896 weld::Container
* pPage
= m_xTabCtrl
->get_page(pDataObject
->sId
);
898 pDataObject
->xTabPage
= (pDataObject
->fnCreatePage
)(pPage
, this, m_pSet
.get());
900 pDataObject
->xTabPage
= (pDataObject
->fnCreatePage
)(pPage
, this, CreateInputItemSet(pDataObject
->sId
));
901 pDataObject
->xTabPage
->SetDialogController(this);
902 SvtViewOptions
aPageOpt(EViewType::TabPage
, pDataObject
->xTabPage
->GetConfigId());
904 Any aUserItem
= aPageOpt
.GetUserItem(USERITEM_NAME
);
906 if ( aUserItem
>>= aTemp
)
908 pDataObject
->xTabPage
->SetUserData(sUserData
);
910 PageCreated(pDataObject
->sId
, *pDataObject
->xTabPage
);
911 if (pDataObject
->xTabPage
->DeferResetToFirstActivation())
912 pDataObject
->bRefresh
= true; // Reset will be called in ActivatePageHdl
914 pDataObject
->xTabPage
->Reset(m_pSet
.get());
918 void SfxTabDialogController::setPreviewsToSamePlace()
920 //where tab pages have the same basic layout with a preview on the right,
921 //get both of their non-preview areas to request the same size so that the
922 //preview appears in the same place in each one so flipping between tabs
923 //isn't distracting as it jumps around
924 std::vector
<std::unique_ptr
<weld::Widget
>> aGrids
;
925 for (auto pDataObject
: m_pImpl
->aData
)
927 if (!pDataObject
->xTabPage
)
929 if (!pDataObject
->xTabPage
->m_xBuilder
)
931 std::unique_ptr
<weld::Widget
> pGrid
= pDataObject
->xTabPage
->m_xBuilder
->weld_widget("maingrid");
934 aGrids
.emplace_back(std::move(pGrid
));
937 m_xSizeGroup
.reset();
939 if (aGrids
.size() <= 1)
942 m_xSizeGroup
= m_xBuilder
->create_size_group();
943 m_xSizeGroup
->set_mode(VclSizeGroupMode::Both
);
944 for (auto& rGrid
: aGrids
)
945 m_xSizeGroup
->add_widget(rGrid
.get());
948 void SfxTabDialogController::RemoveTabPage(const OUString
& rId
)
952 Delete the TabPage with ID nId
957 m_xTabCtrl
->remove_page(rId
);
958 Data_Impl
* pDataObject
= Find( m_pImpl
->aData
, rId
, &nPos
);
962 if ( pDataObject
->xTabPage
)
964 pDataObject
->xTabPage
->FillUserData();
965 OUString
aPageData( pDataObject
->xTabPage
->GetUserData() );
966 if ( !aPageData
.isEmpty() )
968 // save settings of this page (user data)
969 SvtViewOptions
aPageOpt(EViewType::TabPage
, pDataObject
->xTabPage
->GetConfigId());
970 aPageOpt
.SetUserItem( USERITEM_NAME
, Any( aPageData
) );
973 pDataObject
->xTabPage
.reset();
977 m_pImpl
->aData
.erase( m_pImpl
->aData
.begin() + nPos
);
981 SAL_INFO( "sfx.dialog", "TabPage-Id not known" );
985 void SfxTabDialogController::Start_Impl()
989 setPreviewsToSamePlace();
991 assert(m_pImpl
->aData
.size() == static_cast<size_t>(m_xTabCtrl
->get_n_pages())
992 && "not all pages registered");
994 // load old settings, when exists, setting SetCurPageId will override the settings,
995 // something that the sort dialog in calc depends on
996 if (m_sAppPageId
.isEmpty())
998 SvtViewOptions
aDlgOpt(EViewType::TabDialog
, m_xDialog
->get_help_id());
999 if (aDlgOpt
.Exists())
1000 m_xTabCtrl
->set_current_page(aDlgOpt
.GetPageID());
1003 ActivatePage(m_xTabCtrl
->get_current_page_ident());
1005 m_pImpl
->bStarted
= true;
1008 void SfxTabDialogController::SetCurPageId(const OUString
& rIdent
)
1010 m_sAppPageId
= rIdent
;
1011 m_xTabCtrl
->set_current_page(m_sAppPageId
);
1016 The TabPage is activated with the specified Id.
1018 void SfxTabDialogController::ShowPage(const OUString
& rIdent
)
1020 SetCurPageId(rIdent
);
1021 ActivatePage(rIdent
);
1024 OUString
SfxTabDialogController::GetCurPageId() const
1026 return m_xTabCtrl
->get_current_page_ident();
1029 short SfxTabDialogController::run()
1032 return SfxDialogController::run();
1035 bool SfxTabDialogController::runAsync(const std::shared_ptr
<SfxTabDialogController
>& rController
,
1036 const std::function
<void(sal_Int32
)>& rFunc
)
1038 rController
->Start_Impl();
1039 return weld::DialogController::runAsync(rController
, rFunc
);
1042 void SfxTabDialogController::SetInputSet( const SfxItemSet
* pInSet
)
1046 With this method the Input-Set can subsequently be set initially or re-set.
1050 bool bSet
= ( m_pSet
!= nullptr );
1051 m_pSet
.reset(pInSet
? new SfxItemSet(*pInSet
) : nullptr);
1053 if (!bSet
&& !m_xExampleSet
&& !m_pOutSet
&& m_pSet
)
1055 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
1056 m_pOutSet
.reset(new SfxItemSet( *m_pSet
->GetPool(), m_pSet
->GetRanges() ));
1060 SfxItemSet
* SfxTabDialogController::GetInputSetImpl()
1064 Derived classes may create new storage for the InputSet. This has to be
1065 released in the Destructor. To do this, this method must be called.
1069 return m_pSet
.get();
1072 void SfxTabDialogController::RemoveResetButton()
1074 m_xResetBtn
->hide();
1075 m_pImpl
->bHideResetBtn
= true;
1078 void SfxTabDialogController::RemoveStandardButton()
1080 m_xBaseFmtBtn
->hide();
1083 SfxTabPage
* SfxTabDialogController::GetTabPage(std::u16string_view rPageId
) const
1087 Return TabPage with the specified Id.
1091 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, rPageId
);
1093 return pDataObject
->xTabPage
.get();
1097 void SfxTabDialogController::SetApplyHandler(const Link
<weld::Button
&, void>& _rHdl
)
1099 DBG_ASSERT( m_xApplyBtn
, "SfxTabDialog::GetApplyHandler: no apply button enabled!" );
1101 m_xApplyBtn
->connect_clicked(_rHdl
);
1104 bool SfxTabDialogController::Apply()
1106 bool bApplied
= false;
1107 if (PrepareLeaveCurrentPage())
1109 bApplied
= (Ok() == RET_OK
);
1110 //let the pages update their saved values
1111 GetInputSetImpl()->Put(*GetOutputItemSet());
1112 for (auto pDataObject
: m_pImpl
->aData
)
1114 if (!pDataObject
->xTabPage
)
1116 pDataObject
->xTabPage
->ChangesApplied();
1122 std::vector
<OUString
> SfxTabDialogController::getAllPageUIXMLDescriptions() const
1124 int nPages
= m_xTabCtrl
->get_n_pages();
1125 std::vector
<OUString
> aRet
;
1126 aRet
.reserve(nPages
);
1127 for (int i
= 0; i
< nPages
; ++i
)
1128 aRet
.push_back(m_xTabCtrl
->get_page_ident(i
));
1132 bool SfxTabDialogController::selectPageByUIXMLDescription(const OUString
& rUIXMLDescription
)
1134 ShowPage(rUIXMLDescription
);
1135 return m_xTabCtrl
->get_current_page_ident() == rUIXMLDescription
;
1138 BitmapEx
SfxTabDialogController::createScreenshot() const
1140 // if we haven't run Start_Impl yet, do so now to create the initial pages
1141 if (!m_pImpl
->bStarted
)
1143 const_cast<SfxTabDialogController
*>(this)->Start_Impl();
1146 VclPtr
<VirtualDevice
> xDialogSurface(m_xDialog
->screenshot());
1147 return xDialogSurface
->GetBitmapEx(Point(), xDialogSurface
->GetOutputSizePixel());
1150 OUString
SfxTabDialogController::GetScreenshotId() const
1152 const OUString sId
= m_xTabCtrl
->get_current_page_ident();
1153 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, sId
);
1154 SfxTabPage
* pPage
= pDataObject
? pDataObject
->xTabPage
.get() : nullptr;
1157 OUString
sHelpId(pPage
->GetHelpId());
1158 if (!sHelpId
.isEmpty())
1161 return m_xDialog
->get_help_id();
1164 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */