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 OUString USERITEM_NAME
= u
"UserItem"_ustr
;
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
* )
170 Returns the visible strings of a dialog.
180 OUString
SfxTabPage::GetAllStrings() { return OUString(); }
182 void SfxTabPage::Reset( const SfxItemSet
* )
186 bool SfxTabPage::DeferResetToFirstActivation() { return false; }
188 void SfxTabPage::ActivatePage( const SfxItemSet
& )
191 Default implementation of the virtual ActivatePage method. This method is
192 called when a page of dialogue supports the exchange of data between pages.
193 <SfxTabPage::DeactivatePage(SfxItemSet *)>
198 DeactivateRC
SfxTabPage::DeactivatePage( SfxItemSet
* )
202 Default implementation of the virtual DeactivatePage method. This method is
203 called by Sfx when leaving a page; the application can, through the return
204 value, control whether to leave the page. If the page is displayed through
205 bHasExchangeSupport which supports data exchange between pages, then a
206 pointer to the exchange set is passed as parameter. This takes on data for
207 the exchange, then the set is available as a parameter in
208 <SfxTabPage::ActivatePage(const SfxItemSet &)>.
212 DeactivateRC::LeavePage; Allow leaving the page
216 return DeactivateRC::LeavePage
;
220 void SfxTabPage::FillUserData()
224 Virtual method is called by the base class in the destructor to save
225 specific information of the TabPage in the ini-file. When overriding a
226 string must be compiled, which is then flushed with the <SetUserData()>.
233 bool SfxTabPage::IsReadOnly() const
239 const SfxPoolItem
* SfxTabPage::GetItem( const SfxItemSet
& rSet
, sal_uInt16 nSlot
, bool bDeep
)
243 static Method: hereby are the implementations of the TabPage code
248 const SfxItemPool
* pPool
= rSet
.GetPool();
249 sal_uInt16 nWh
= pPool
->GetWhich( nSlot
, bDeep
);
250 const SfxPoolItem
* pItem
= nullptr;
251 rSet
.GetItemState( nWh
, true, &pItem
);
253 if ( !pItem
&& nWh
!= nSlot
)
254 pItem
= &pPool
->GetDefaultItem( nWh
);
259 const SfxPoolItem
* SfxTabPage::GetOldItem( const SfxItemSet
& rSet
,
260 sal_uInt16 nSlot
, bool bDeep
)
264 This method returns an attribute for comparison of the old value.
268 const SfxItemSet
& rOldSet
= GetItemSet();
269 sal_uInt16 nWh
= GetWhich( nSlot
, bDeep
);
270 const SfxPoolItem
* pItem
= nullptr;
272 if (mpImpl
->mbStandard
&& rOldSet
.GetParent())
273 pItem
= GetItem( *rOldSet
.GetParent(), nSlot
);
274 else if ( rSet
.GetParent() &&
275 SfxItemState::DONTCARE
== rSet
.GetItemState( nWh
) )
276 pItem
= GetItem( *rSet
.GetParent(), nSlot
);
278 pItem
= GetItem( rOldSet
, nSlot
);
282 void SfxTabPage::PageCreated( const SfxAllItemSet
& /*aSet*/ )
284 SAL_WARN( "sfx.dialog", "SfxTabPage::PageCreated should not be called");
287 void SfxTabPage::ChangesApplied()
291 void SfxTabPage::SetDialogController(SfxOkDialogController
* pDialog
)
293 mpImpl
->mpSfxDialogController
= pDialog
;
294 m_pDialogController
= mpImpl
->mpSfxDialogController
;
297 SfxOkDialogController
* SfxTabPage::GetDialogController() const
299 return mpImpl
->mpSfxDialogController
;
302 OUString
SfxTabPage::GetHelpId() const
305 return m_xContainer
->get_help_id();
309 weld::Window
* SfxTabPage::GetFrameWeld() const
311 if (m_pDialogController
)
312 return m_pDialogController
->getDialog();
316 const SfxItemSet
* SfxTabPage::GetDialogExampleSet() const
318 if (mpImpl
->mpSfxDialogController
)
319 return mpImpl
->mpSfxDialogController
->GetExampleSet();
323 SfxTabDialogController::SfxTabDialogController
325 weld::Widget
* pParent
, // Parent Window
326 const OUString
& rUIXMLDescription
, const OUString
& rID
, // Dialog .ui path, Dialog Name
327 const SfxItemSet
* pItemSet
, // Itemset with the data;
328 // can be NULL, when Pages are onDemand
329 bool bEditFmt
// when yes -> additional Button for standard
331 : SfxOkDialogController(pParent
, rUIXMLDescription
, rID
)
332 , m_xTabCtrl(m_xBuilder
->weld_notebook("tabcontrol"))
333 , m_xOKBtn(m_xBuilder
->weld_button("ok"))
334 , m_xApplyBtn(m_xBuilder
->weld_button("apply"))
335 , m_xUserBtn(m_xBuilder
->weld_button("user"))
336 , m_xCancelBtn(m_xBuilder
->weld_button("cancel"))
337 , m_xResetBtn(m_xBuilder
->weld_button("reset"))
338 , m_xBaseFmtBtn(m_xBuilder
->weld_button("standard"))
339 , m_pSet(pItemSet
? new SfxItemSet(*pItemSet
) : nullptr)
340 , m_bStandardPushed(false)
342 m_pImpl
.reset(new TabDlg_Impl(m_xTabCtrl
->get_n_pages()));
343 m_pImpl
->bHideResetBtn
= !m_xResetBtn
->get_visible();
344 m_xOKBtn
->connect_clicked(LINK(this, SfxTabDialogController
, OkHdl
));
345 m_xCancelBtn
->connect_clicked(LINK(this, SfxTabDialogController
, CancelHdl
));
346 m_xResetBtn
->connect_clicked(LINK(this, SfxTabDialogController
, ResetHdl
));
347 m_xResetBtn
->set_label(SfxResId(STR_RESET
));
348 m_xTabCtrl
->connect_enter_page(LINK(this, SfxTabDialogController
, ActivatePageHdl
));
349 m_xTabCtrl
->connect_leave_page(LINK(this, SfxTabDialogController
, DeactivatePageHdl
));
350 m_xResetBtn
->set_help_id(HID_TABDLG_RESET_BTN
);
354 m_xBaseFmtBtn
->set_label(SfxResId(STR_STANDARD_SHORTCUT
));
355 m_xBaseFmtBtn
->connect_clicked(LINK(this, SfxTabDialogController
, BaseFmtHdl
));
356 m_xBaseFmtBtn
->set_help_id(HID_TABDLG_STANDARD_BTN
);
357 m_xBaseFmtBtn
->show();
361 m_xUserBtn
->connect_clicked(LINK(this, SfxTabDialogController
, UserHdl
));
365 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
366 m_pOutSet
.reset(new SfxItemSet(*m_pSet
->GetPool(), m_pSet
->GetRanges()));
369 // The reset functionality seems to be confusing to many; disable in LOK.
370 if (comphelper::LibreOfficeKit::isActive())
374 IMPL_LINK_NOARG(SfxTabDialogController
, OkHdl
, weld::Button
&, void)
378 Handler of the Ok-Buttons
379 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
380 Returns <DeactivateRC::LeavePage>, <SfxTabDialog::Ok()> is called
381 and the Dialog is ended.
385 if (PrepareLeaveCurrentPage())
386 m_xDialog
->response(Ok());
389 IMPL_LINK_NOARG(SfxTabDialogController
, UserHdl
, weld::Button
&, void)
393 Handler of the User-Buttons
394 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
395 returns this <DeactivateRC::LeavePage> and <SfxTabDialog::Ok()> is called.
396 Then the Dialog is ended with the Return value <SfxTabDialog::Ok()>
400 if (PrepareLeaveCurrentPage())
407 m_xDialog
->response(nRet
);
411 IMPL_LINK_NOARG(SfxTabDialogController
, CancelHdl
, weld::Button
&, void)
413 m_xDialog
->response(RET_CANCEL
);
416 IMPL_LINK_NOARG(SfxTabDialogController
, ResetHdl
, weld::Button
&, void)
420 Handler behind the reset button.
421 The Current Page is new initialized with their initial data, all the
422 settings that the user has made on this page are repealed.
426 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, m_xTabCtrl
->get_current_page_ident());
427 assert(pDataObject
&& "Id not known");
429 pDataObject
->xTabPage
->Reset(m_pSet
.get());
430 // Also reset relevant items of ExampleSet and OutSet to initial state
431 if (!pDataObject
->fnGetRanges
)
435 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
437 const SfxItemPool
* pPool
= m_pSet
->GetPool();
438 const WhichRangesContainer
& pTmpRanges
= (pDataObject
->fnGetRanges
)();
440 for (const auto & rPair
: pTmpRanges
)
442 // Correct Range with multiple values
443 sal_uInt16 nTmp
= rPair
.first
, nTmpEnd
= rPair
.second
;
444 DBG_ASSERT(nTmp
<= nTmpEnd
, "Range is sorted the wrong way");
448 // If really sorted wrongly, then set new
449 std::swap(nTmp
, nTmpEnd
);
452 while (nTmp
&& nTmp
<= nTmpEnd
)
454 // Iterate over the Range and set the Items
455 sal_uInt16 nWh
= pPool
->GetWhich(nTmp
);
456 const SfxPoolItem
* pItem
;
457 if (SfxItemState::SET
== m_pSet
->GetItemState(nWh
, false, &pItem
))
459 m_xExampleSet
->Put(*pItem
);
463 m_xExampleSet
->ClearItem(nWh
);
465 m_pOutSet
->ClearItem(nWh
);
473 Handler behind the Standard-Button.
474 This button is available when editing style sheets. All the set attributes
475 in the edited stylesheet are deleted.
477 IMPL_LINK_NOARG(SfxTabDialogController
, BaseFmtHdl
, weld::Button
&, void)
479 m_bStandardPushed
= true;
481 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, m_xTabCtrl
->get_current_page_ident());
482 assert(pDataObject
&& "Id not known");
484 if (!pDataObject
->fnGetRanges
)
488 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
490 const SfxItemPool
* pPool
= m_pSet
->GetPool();
491 const WhichRangesContainer
& pTmpRanges
= (pDataObject
->fnGetRanges
)();
492 SfxItemSet
aTmpSet(*m_xExampleSet
);
494 for (const auto& rPair
: pTmpRanges
)
496 // Correct Range with multiple values
497 sal_uInt16 nTmp
= rPair
.first
, nTmpEnd
= rPair
.second
;
498 DBG_ASSERT( nTmp
<= nTmpEnd
, "Range is sorted the wrong way" );
500 if ( nTmp
> nTmpEnd
)
502 // If really sorted wrongly, then set new
503 std::swap(nTmp
, nTmpEnd
);
506 while ( nTmp
&& nTmp
<= nTmpEnd
) // guard against overflow
508 // Iterate over the Range and set the Items
509 sal_uInt16 nWh
= pPool
->GetWhich(nTmp
);
510 m_xExampleSet
->ClearItem(nWh
);
511 aTmpSet
.ClearItem(nWh
);
512 // At the Outset of InvalidateItem,
513 // so that the change takes effect
514 m_pOutSet
->InvalidateItem(nWh
);
518 // Set all Items as new -> the call the current Page Reset()
519 assert(pDataObject
->xTabPage
&& "the Page is gone");
520 pDataObject
->xTabPage
->Reset( &aTmpSet
);
521 pDataObject
->xTabPage
->mpImpl
->mbStandard
= true;
524 IMPL_LINK(SfxTabDialogController
, ActivatePageHdl
, const OUString
&, rPage
, void)
529 void SfxTabDialogController::ActivatePage(const OUString
& rPage
)
532 Handler that is called by StarView for switching to a different page.
533 If possible the <SfxTabPage::Reset(const SfxItemSet &)> or
534 <SfxTabPage::ActivatePage(const SfxItemSet &)> is called on the new page
538 assert(!m_pImpl
->aData
.empty() && "no Pages registered");
539 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, rPage
);
542 SAL_WARN("sfx.dialog", "Tab Page ID '" << rPage
<< "' not known, this is pretty serious and needs investigation");
546 SfxTabPage
* pTabPage
= pDataObject
->xTabPage
.get();
550 if (pDataObject
->bRefresh
)
551 pTabPage
->Reset(m_pSet
.get());
552 pDataObject
->bRefresh
= false;
555 pTabPage
->ActivatePage(*m_xExampleSet
);
557 if (pTabPage
->IsReadOnly() || m_pImpl
->bHideResetBtn
)
563 IMPL_LINK(SfxTabDialogController
, DeactivatePageHdl
, const OUString
&, rPage
, bool)
565 return DeactivatePage(rPage
);
568 bool SfxTabDialogController::DeactivatePage(std::u16string_view aPage
)
571 Handler that is called by StarView before leaving a page.
575 <SfxTabPage::DeactivatePage(SfxItemSet *)>
579 assert(!m_pImpl
->aData
.empty() && "no Pages registered");
580 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, aPage
);
583 SAL_WARN("sfx.dialog", "Tab Page ID not known, this is pretty serious and needs investigation");
587 SfxTabPage
* pPage
= pDataObject
->xTabPage
.get();
591 DeactivateRC nRet
= DeactivateRC::LeavePage
;
593 if (!m_xExampleSet
&& pPage
->HasExchangeSupport() && m_pSet
)
594 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
->GetPool(), m_pSet
->GetRanges()));
598 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
600 if (pPage
->HasExchangeSupport())
601 nRet
= pPage
->DeactivatePage(&aTmp
);
603 nRet
= pPage
->DeactivatePage(nullptr);
604 if ( ( DeactivateRC::LeavePage
& nRet
) == DeactivateRC::LeavePage
&&
605 aTmp
.Count() && m_xExampleSet
)
607 m_xExampleSet
->Put( aTmp
);
608 m_pOutSet
->Put( aTmp
);
613 if ( pPage
->HasExchangeSupport() ) //!!!
617 SfxItemPool
* pPool
= pPage
->GetItemSet().GetPool();
618 m_xExampleSet
.reset(new SfxItemSet(*pPool
, GetInputRanges(*pPool
)));
620 nRet
= pPage
->DeactivatePage(m_xExampleSet
.get());
623 nRet
= pPage
->DeactivatePage( nullptr );
626 if ( nRet
& DeactivateRC::RefreshSet
)
629 // Flag all Pages as to be initialized as new
631 for (auto const& elem
: m_pImpl
->aData
)
633 elem
->bRefresh
= ( elem
->xTabPage
.get() != pPage
); // Do not refresh own Page anymore
636 return static_cast<bool>(nRet
& DeactivateRC::LeavePage
);
639 bool SfxTabDialogController::PrepareLeaveCurrentPage()
641 const OUString sId
= m_xTabCtrl
->get_current_page_ident();
642 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, sId
);
643 DBG_ASSERT( pDataObject
, "Id not known" );
644 SfxTabPage
* pPage
= pDataObject
? pDataObject
->xTabPage
.get() : nullptr;
650 DeactivateRC nRet
= DeactivateRC::LeavePage
;
653 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
655 if ( pPage
->HasExchangeSupport() )
656 nRet
= pPage
->DeactivatePage( &aTmp
);
658 nRet
= pPage
->DeactivatePage( nullptr );
660 if ( ( DeactivateRC::LeavePage
& nRet
) == DeactivateRC::LeavePage
663 m_xExampleSet
->Put( aTmp
);
664 m_pOutSet
->Put( aTmp
);
668 nRet
= pPage
->DeactivatePage( nullptr );
669 bEnd
= nRet
!= DeactivateRC::KeepPage
;
675 const WhichRangesContainer
& SfxTabDialogController::GetInputRanges(const SfxItemPool
& rPool
)
679 Makes the set over the range of all pages of the dialogue. Pages have the
680 static method for querying their range in AddTabPage, ie deliver their
685 Pointer to a null-terminated array of sal_uInt16. This array belongs to the
686 dialog and is deleted when the dialogue is destroy.
690 <SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, bool)>
691 <SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)>
692 <SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)>
698 SAL_WARN( "sfx.dialog", "Set already exists!" );
699 return m_pSet
->GetRanges();
702 if ( !m_pRanges
.empty() )
704 SfxItemSet
aUS(const_cast<SfxItemPool
&>(rPool
));
706 for (auto const& elem
: m_pImpl
->aData
)
709 if ( elem
->fnGetRanges
)
711 const WhichRangesContainer
& pTmpRanges
= (elem
->fnGetRanges
)();
713 for (const auto & rPair
: pTmpRanges
)
715 sal_uInt16 nWidFrom
= rPool
.GetWhich(rPair
.first
);
716 sal_uInt16 nWidTo
= rPool
.GetWhich(rPair
.second
);
717 aUS
.MergeRange(nWidFrom
, nWidTo
); // Keep it valid
722 m_pRanges
= aUS
.GetRanges();
726 SfxTabDialogController::~SfxTabDialogController()
730 for (auto & elem
: m_pImpl
->aData
)
732 if ( elem
->xTabPage
)
734 // save settings of all pages (user data)
735 elem
->xTabPage
->FillUserData();
736 OUString
aPageData( elem
->xTabPage
->GetUserData() );
737 if ( !aPageData
.isEmpty() )
739 // save settings of all pages (user data)
740 SvtViewOptions
aPageOpt(EViewType::TabPage
, elem
->xTabPage
->GetConfigId());
741 aPageOpt
.SetUserItem( USERITEM_NAME
, Any( aPageData
) );
744 elem
->xTabPage
.reset();
751 short SfxTabDialogController::Ok()
755 Ok handler for the Dialogue.
757 Dialog's current location and current page are saved for the next time
760 The OutputSet is created and for each page this or the special OutputSet
761 is set by calling the method <SfxTabPage::FillItemSet(SfxItemSet &)>, to
762 insert the entered data by the user into the set.
766 RET_OK: if at least one page has returned from FillItemSet,
767 otherwise RET_CANCEL.
770 SavePosAndId(); //See fdo#38828 "Apply" resetting window position
775 m_pOutSet
.reset(new SfxItemSet( *m_xExampleSet
));
777 m_pOutSet
= m_pSet
->Clone( false ); // without Items
779 bool bModified
= false;
781 for (auto const& elem
: m_pImpl
->aData
)
783 SfxTabPage
* pTabPage
= elem
->xTabPage
.get();
787 if ( m_pSet
&& !pTabPage
->HasExchangeSupport() )
789 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
791 if ( pTabPage
->FillItemSet( &aTmp
) )
795 m_xExampleSet
->Put( aTmp
);
796 m_pOutSet
->Put( aTmp
);
802 if (m_pOutSet
&& m_pOutSet
->Count() > 0)
805 if (m_bStandardPushed
)
808 return bModified
? RET_OK
: RET_CANCEL
;
811 void SfxTabDialogController::RefreshInputSet()
815 Default implementation of the virtual Method.
816 This is called, when <SfxTabPage::DeactivatePage(SfxItemSet *)>
817 returns <DeactivateRC::RefreshSet>.
821 SAL_INFO ( "sfx.dialog", "RefreshInputSet not implemented" );
824 void SfxTabDialogController::PageCreated
828 Default implementation of the virtual method. This is called immediately
829 after creating a page. Here the dialogue can call the TabPage Method
834 const OUString
&, // Id of the created page
835 SfxTabPage
& // Reference to the created page
840 void SfxTabDialogController::SavePosAndId()
842 // save settings (screen position and current page)
843 SvtViewOptions
aDlgOpt(EViewType::TabDialog
, m_xDialog
->get_help_id());
844 aDlgOpt
.SetPageID(m_xTabCtrl
->get_current_page_ident());
848 Adds a page to the dialog. The Name must correspond to an entry in the
849 TabControl in the dialog .ui
851 void SfxTabDialogController::AddTabPage(const OUString
&rName
/* Page ID */,
852 CreateTabPage pCreateFunc
/* Pointer to the Factory Method */,
853 GetTabPageRanges pRangesFunc
/* Pointer to the Method for querying Ranges onDemand */)
855 m_pImpl
->aData
.push_back(new Data_Impl(rName
, pCreateFunc
, pRangesFunc
));
858 void SfxTabDialogController::AddTabPage(const OUString
&rName
/* Page ID */,
859 sal_uInt16 nPageCreateId
/* Identifier of the Factory Method to create the page */)
861 SfxAbstractDialogFactory
* pFact
= SfxAbstractDialogFactory::Create();
862 CreateTabPage pCreateFunc
= pFact
->GetTabPageCreatorFunc(nPageCreateId
);
863 GetTabPageRanges pRangesFunc
= pFact
->GetTabPageRangesFunc(nPageCreateId
);
864 AddTabPage(rName
, pCreateFunc
, pRangesFunc
);
869 Add a page to the dialog. The Rider text is passed on, the page has no
870 counterpart in the TabControl in the resource of the dialogue.
873 void SfxTabDialogController::AddTabPage(const OUString
&rName
, /* Page ID */
874 const OUString
& rRiderText
,
875 CreateTabPage pCreateFunc
/* Pointer to the Factory Method */)
877 assert(!m_xTabCtrl
->get_page(rName
) && "Double Page-Ids in the Tabpage");
878 m_xTabCtrl
->append_page(rName
, rRiderText
);
879 AddTabPage(rName
, pCreateFunc
, nullptr);
882 void SfxTabDialogController::AddTabPage(const OUString
&rName
, const OUString
& rRiderText
,
883 sal_uInt16 nPageCreateId
/* Identifier of the Factory Method to create the page */)
885 assert(!m_xTabCtrl
->get_page(rName
) && "Double Page-Ids in the Tabpage");
886 m_xTabCtrl
->append_page(rName
, rRiderText
);
887 AddTabPage(rName
, nPageCreateId
);
892 Default implementation of the virtual Method.
893 This is called when pages create their sets onDemand.
895 SfxItemSet
* SfxTabDialogController::CreateInputItemSet(const OUString
&)
897 SAL_WARN( "sfx.dialog", "CreateInputItemSet not implemented" );
898 m_xItemSet
= std::make_unique
<SfxAllItemSet
>(SfxGetpApp()->GetPool());
899 return m_xItemSet
.get();
902 void SfxTabDialogController::CreatePages()
904 for (auto pDataObject
: m_pImpl
->aData
)
906 if (pDataObject
->xTabPage
)
908 weld::Container
* pPage
= m_xTabCtrl
->get_page(pDataObject
->sId
);
910 pDataObject
->xTabPage
= (pDataObject
->fnCreatePage
)(pPage
, this, m_pSet
.get());
912 pDataObject
->xTabPage
= (pDataObject
->fnCreatePage
)(pPage
, this, CreateInputItemSet(pDataObject
->sId
));
913 pDataObject
->xTabPage
->SetDialogController(this);
914 SvtViewOptions
aPageOpt(EViewType::TabPage
, pDataObject
->xTabPage
->GetConfigId());
916 Any aUserItem
= aPageOpt
.GetUserItem(USERITEM_NAME
);
918 if ( aUserItem
>>= aTemp
)
920 pDataObject
->xTabPage
->SetUserData(sUserData
);
922 PageCreated(pDataObject
->sId
, *pDataObject
->xTabPage
);
923 if (pDataObject
->xTabPage
->DeferResetToFirstActivation())
924 pDataObject
->bRefresh
= true; // Reset will be called in ActivatePageHdl
926 pDataObject
->xTabPage
->Reset(m_pSet
.get());
930 void SfxTabDialogController::setPreviewsToSamePlace()
932 //where tab pages have the same basic layout with a preview on the right,
933 //get both of their non-preview areas to request the same size so that the
934 //preview appears in the same place in each one so flipping between tabs
935 //isn't distracting as it jumps around
936 std::vector
<std::unique_ptr
<weld::Widget
>> aGrids
;
937 for (auto pDataObject
: m_pImpl
->aData
)
939 if (!pDataObject
->xTabPage
)
941 if (!pDataObject
->xTabPage
->m_xBuilder
)
943 std::unique_ptr
<weld::Widget
> pGrid
= pDataObject
->xTabPage
->m_xBuilder
->weld_widget("maingrid");
946 aGrids
.emplace_back(std::move(pGrid
));
949 m_xSizeGroup
.reset();
951 if (aGrids
.size() <= 1)
954 m_xSizeGroup
= m_xBuilder
->create_size_group();
955 m_xSizeGroup
->set_mode(VclSizeGroupMode::Both
);
956 for (auto& rGrid
: aGrids
)
957 m_xSizeGroup
->add_widget(rGrid
.get());
960 void SfxTabDialogController::RemoveTabPage(const OUString
& rId
)
964 Delete the TabPage with ID nId
969 m_xTabCtrl
->remove_page(rId
);
970 Data_Impl
* pDataObject
= Find( m_pImpl
->aData
, rId
, &nPos
);
974 if ( pDataObject
->xTabPage
)
976 pDataObject
->xTabPage
->FillUserData();
977 OUString
aPageData( pDataObject
->xTabPage
->GetUserData() );
978 if ( !aPageData
.isEmpty() )
980 // save settings of this page (user data)
981 SvtViewOptions
aPageOpt(EViewType::TabPage
, pDataObject
->xTabPage
->GetConfigId());
982 aPageOpt
.SetUserItem( USERITEM_NAME
, Any( aPageData
) );
985 pDataObject
->xTabPage
.reset();
989 m_pImpl
->aData
.erase( m_pImpl
->aData
.begin() + nPos
);
993 SAL_INFO( "sfx.dialog", "TabPage-Id not known" );
997 void SfxTabDialogController::Start_Impl()
1001 setPreviewsToSamePlace();
1003 assert(m_pImpl
->aData
.size() == static_cast<size_t>(m_xTabCtrl
->get_n_pages())
1004 && "not all pages registered");
1006 // load old settings, when exists, setting SetCurPageId will override the settings,
1007 // something that the sort dialog in calc depends on
1008 if (m_sAppPageId
.isEmpty())
1010 SvtViewOptions
aDlgOpt(EViewType::TabDialog
, m_xDialog
->get_help_id());
1011 if (aDlgOpt
.Exists())
1012 m_xTabCtrl
->set_current_page(aDlgOpt
.GetPageID());
1015 ActivatePage(m_xTabCtrl
->get_current_page_ident());
1017 m_pImpl
->bStarted
= true;
1020 void SfxTabDialogController::SetCurPageId(const OUString
& rIdent
)
1022 m_sAppPageId
= rIdent
;
1023 m_xTabCtrl
->set_current_page(m_sAppPageId
);
1028 The TabPage is activated with the specified Id.
1030 void SfxTabDialogController::ShowPage(const OUString
& rIdent
)
1032 SetCurPageId(rIdent
);
1033 ActivatePage(rIdent
);
1036 OUString
SfxTabDialogController::GetCurPageId() const
1038 return m_xTabCtrl
->get_current_page_ident();
1041 short SfxTabDialogController::run()
1044 return SfxDialogController::run();
1047 bool SfxTabDialogController::runAsync(const std::shared_ptr
<SfxTabDialogController
>& rController
,
1048 const std::function
<void(sal_Int32
)>& rFunc
)
1050 rController
->Start_Impl();
1051 return weld::DialogController::runAsync(rController
, rFunc
);
1054 void SfxTabDialogController::SetInputSet( const SfxItemSet
* pInSet
)
1058 With this method the Input-Set can subsequently be set initially or re-set.
1062 bool bSet
= ( m_pSet
!= nullptr );
1063 m_pSet
.reset(pInSet
? new SfxItemSet(*pInSet
) : nullptr);
1065 if (!bSet
&& !m_xExampleSet
&& !m_pOutSet
&& m_pSet
)
1067 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
1068 m_pOutSet
.reset(new SfxItemSet( *m_pSet
->GetPool(), m_pSet
->GetRanges() ));
1072 SfxItemSet
* SfxTabDialogController::GetInputSetImpl()
1076 Derived classes may create new storage for the InputSet. This has to be
1077 released in the Destructor. To do this, this method must be called.
1081 return m_pSet
.get();
1084 void SfxTabDialogController::RemoveResetButton()
1086 m_xResetBtn
->hide();
1087 m_pImpl
->bHideResetBtn
= true;
1090 void SfxTabDialogController::RemoveStandardButton()
1092 m_xBaseFmtBtn
->hide();
1095 SfxTabPage
* SfxTabDialogController::GetTabPage(std::u16string_view rPageId
) const
1099 Return TabPage with the specified Id.
1103 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, rPageId
);
1105 return pDataObject
->xTabPage
.get();
1109 void SfxTabDialogController::SetApplyHandler(const Link
<weld::Button
&, void>& _rHdl
)
1111 DBG_ASSERT( m_xApplyBtn
, "SfxTabDialog::GetApplyHandler: no apply button enabled!" );
1113 m_xApplyBtn
->connect_clicked(_rHdl
);
1116 bool SfxTabDialogController::Apply()
1118 bool bApplied
= false;
1119 if (PrepareLeaveCurrentPage())
1121 bApplied
= (Ok() == RET_OK
);
1122 //let the pages update their saved values
1123 GetInputSetImpl()->Put(*GetOutputItemSet());
1124 for (auto pDataObject
: m_pImpl
->aData
)
1126 if (!pDataObject
->xTabPage
)
1128 pDataObject
->xTabPage
->ChangesApplied();
1134 std::vector
<OUString
> SfxTabDialogController::getAllPageUIXMLDescriptions() const
1136 int nPages
= m_xTabCtrl
->get_n_pages();
1137 std::vector
<OUString
> aRet
;
1138 aRet
.reserve(nPages
);
1139 for (int i
= 0; i
< nPages
; ++i
)
1140 aRet
.push_back(m_xTabCtrl
->get_page_ident(i
));
1144 bool SfxTabDialogController::selectPageByUIXMLDescription(const OUString
& rUIXMLDescription
)
1146 ShowPage(rUIXMLDescription
);
1147 return m_xTabCtrl
->get_current_page_ident() == rUIXMLDescription
;
1150 BitmapEx
SfxTabDialogController::createScreenshot() const
1152 // if we haven't run Start_Impl yet, do so now to create the initial pages
1153 if (!m_pImpl
->bStarted
)
1155 const_cast<SfxTabDialogController
*>(this)->Start_Impl();
1158 VclPtr
<VirtualDevice
> xDialogSurface(m_xDialog
->screenshot());
1159 return xDialogSurface
->GetBitmapEx(Point(), xDialogSurface
->GetOutputSizePixel());
1162 OUString
SfxTabDialogController::GetScreenshotId() const
1164 const OUString sId
= m_xTabCtrl
->get_current_page_ident();
1165 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, sId
);
1166 SfxTabPage
* pPage
= pDataObject
? pDataObject
->xTabPage
.get() : nullptr;
1169 OUString
sHelpId(pPage
->GetHelpId());
1170 if (!sHelpId
.isEmpty())
1173 return m_xDialog
->get_help_id();
1176 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */