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>
31 #include <vcl/virdev.hxx>
32 #include <sal/log.hxx>
33 #include <tools/debug.hxx>
34 #include <comphelper/lok.hxx>
36 #include <sfx2/strings.hrc>
39 using namespace ::com::sun::star::uno
;
41 constexpr OUStringLiteral USERITEM_NAME
= u
"UserItem";
47 SfxOkDialogController
* mpSfxDialogController
;
48 css::uno::Reference
< css::frame::XFrame
> mxFrame
;
50 TabPageImpl() : mbStandard(false), mpSfxDialogController(nullptr) {}
57 OString sId
; // The ID
58 CreateTabPage fnCreatePage
; // Pointer to Factory
59 GetTabPageRanges fnGetRanges
; // Pointer to Ranges-Function
60 std::unique_ptr
<SfxTabPage
> xTabPage
; // The TabPage itself
61 bool bRefresh
; // Flag: Page must be re-initialized
64 Data_Impl( const OString
& rId
, CreateTabPage fnPage
,
65 GetTabPageRanges fnRanges
) :
68 fnCreatePage( fnPage
),
69 fnGetRanges ( fnRanges
),
77 SfxTabDialogItem::SfxTabDialogItem( const SfxTabDialogItem
& rAttr
, SfxItemPool
* pItemPool
)
78 : SfxSetItem( rAttr
, pItemPool
)
82 SfxTabDialogItem::SfxTabDialogItem( sal_uInt16 nId
, const SfxItemSet
& rItemSet
)
83 : SfxSetItem( nId
, rItemSet
)
87 SfxTabDialogItem
* SfxTabDialogItem::Clone(SfxItemPool
* pToPool
) const
89 return new SfxTabDialogItem( *this, pToPool
);
92 typedef std::vector
<Data_Impl
*> SfxTabDlgData_Impl
;
96 bool bHideResetBtn
: 1;
98 SfxTabDlgData_Impl aData
;
100 explicit TabDlg_Impl(sal_uInt8 nCnt
)
101 : bHideResetBtn(false)
104 aData
.reserve( nCnt
);
108 static Data_Impl
* Find( const SfxTabDlgData_Impl
& rArr
, std::string_view rId
, sal_uInt16
* pPos
= nullptr)
110 const sal_uInt16 nCount
= rArr
.size();
112 for ( sal_uInt16 i
= 0; i
< nCount
; ++i
)
114 Data_Impl
* pObj
= rArr
[i
];
116 if ( pObj
->sId
== rId
)
126 void SfxTabPage::SetFrame(const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
129 pImpl
->mxFrame
= xFrame
;
132 css::uno::Reference
< css::frame::XFrame
> SfxTabPage::GetFrame() const
135 return pImpl
->mxFrame
;
136 return css::uno::Reference
< css::frame::XFrame
>();
139 SfxTabPage::SfxTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const OUString
& rUIXMLDescription
, const OString
& rID
, const SfxItemSet
*rAttrSet
)
140 : BuilderPage(pPage
, pController
, rUIXMLDescription
, rID
,
141 comphelper::LibreOfficeKit::isActive() && SfxViewShell::Current()
142 && SfxViewShell::Current()->isLOKMobilePhone())
144 , bHasExchangeSupport ( false )
145 , pImpl ( new TabPageImpl
)
147 pImpl
->mpSfxDialogController
= dynamic_cast<SfxOkDialogController
*>(m_pDialogController
);
150 SfxTabPage::~SfxTabPage()
154 std::unique_ptr
<weld::Container
> xParent(m_xContainer
->weld_parent());
156 xParent
->move(m_xContainer
.get(), nullptr);
158 m_xContainer
.reset();
163 bool SfxTabPage::FillItemSet( SfxItemSet
* )
168 void SfxTabPage::Reset( const SfxItemSet
* )
172 bool SfxTabPage::DeferResetToFirstActivation() { return false; }
174 void SfxTabPage::ActivatePage( const SfxItemSet
& )
177 Default implementation of the virtual ActivatePage method. This method is
178 called when a page of dialogue supports the exchange of data between pages.
179 <SfxTabPage::DeactivatePage(SfxItemSet *)>
184 DeactivateRC
SfxTabPage::DeactivatePage( SfxItemSet
* )
188 Default implementation of the virtual DeactivatePage method. This method is
189 called by Sfx when leaving a page; the application can, through the return
190 value, control whether to leave the page. If the page is displayed through
191 bHasExchangeSupport which supports data exchange between pages, then a
192 pointer to the exchange set is passed as parameter. This takes on data for
193 the exchange, then the set is available as a parameter in
194 <SfxTabPage::ActivatePage(const SfxItemSet &)>.
198 DeactivateRC::LeavePage; Allow leaving the page
202 return DeactivateRC::LeavePage
;
206 void SfxTabPage::FillUserData()
210 Virtual method is called by the base class in the destructor to save
211 specific information of the TabPage in the ini-file. When overriding a
212 string must be compiled, which is then flushed with the <SetUserData()>.
219 bool SfxTabPage::IsReadOnly() const
225 const SfxPoolItem
* SfxTabPage::GetItem( const SfxItemSet
& rSet
, sal_uInt16 nSlot
, bool bDeep
)
229 static Method: hereby are the implementations of the TabPage code
234 const SfxItemPool
* pPool
= rSet
.GetPool();
235 sal_uInt16 nWh
= pPool
->GetWhich( nSlot
, bDeep
);
236 const SfxPoolItem
* pItem
= nullptr;
237 rSet
.GetItemState( nWh
, true, &pItem
);
239 if ( !pItem
&& nWh
!= nSlot
)
240 pItem
= &pPool
->GetDefaultItem( nWh
);
245 const SfxPoolItem
* SfxTabPage::GetOldItem( const SfxItemSet
& rSet
,
246 sal_uInt16 nSlot
, bool bDeep
)
250 This method returns an attribute for comparison of the old value.
254 const SfxItemSet
& rOldSet
= GetItemSet();
255 sal_uInt16 nWh
= GetWhich( nSlot
, bDeep
);
256 const SfxPoolItem
* pItem
= nullptr;
258 if ( pImpl
->mbStandard
&& rOldSet
.GetParent() )
259 pItem
= GetItem( *rOldSet
.GetParent(), nSlot
);
260 else if ( rSet
.GetParent() &&
261 SfxItemState::DONTCARE
== rSet
.GetItemState( nWh
) )
262 pItem
= GetItem( *rSet
.GetParent(), nSlot
);
264 pItem
= GetItem( rOldSet
, nSlot
);
268 void SfxTabPage::PageCreated( const SfxAllItemSet
& /*aSet*/ )
270 SAL_WARN( "sfx.dialog", "SfxTabPage::PageCreated should not be called");
273 void SfxTabPage::ChangesApplied()
277 void SfxTabPage::SetDialogController(SfxOkDialogController
* pDialog
)
279 pImpl
->mpSfxDialogController
= pDialog
;
280 m_pDialogController
= pImpl
->mpSfxDialogController
;
283 SfxOkDialogController
* SfxTabPage::GetDialogController() const
285 return pImpl
->mpSfxDialogController
;
288 OString
SfxTabPage::GetHelpId() const
291 return m_xContainer
->get_help_id();
295 weld::Window
* SfxTabPage::GetFrameWeld() const
297 if (m_pDialogController
)
298 return m_pDialogController
->getDialog();
302 const SfxItemSet
* SfxTabPage::GetDialogExampleSet() const
304 if (pImpl
->mpSfxDialogController
)
305 return pImpl
->mpSfxDialogController
->GetExampleSet();
309 SfxTabDialogController::SfxTabDialogController
311 weld::Widget
* pParent
, // Parent Window
312 const OUString
& rUIXMLDescription
, const OString
& rID
, // Dialog .ui path, Dialog Name
313 const SfxItemSet
* pItemSet
, // Itemset with the data;
314 // can be NULL, when Pages are onDemand
315 bool bEditFmt
// when yes -> additional Button for standard
317 : SfxOkDialogController(pParent
, rUIXMLDescription
, rID
)
318 , m_xTabCtrl(m_xBuilder
->weld_notebook("tabcontrol"))
319 , m_xOKBtn(m_xBuilder
->weld_button("ok"))
320 , m_xApplyBtn(m_xBuilder
->weld_button("apply"))
321 , m_xUserBtn(m_xBuilder
->weld_button("user"))
322 , m_xCancelBtn(m_xBuilder
->weld_button("cancel"))
323 , m_xResetBtn(m_xBuilder
->weld_button("reset"))
324 , m_xBaseFmtBtn(m_xBuilder
->weld_button("standard"))
325 , m_pSet(pItemSet
? new SfxItemSet(*pItemSet
) : nullptr)
326 , m_bStandardPushed(false)
328 m_pImpl
.reset(new TabDlg_Impl(m_xTabCtrl
->get_n_pages()));
329 m_pImpl
->bHideResetBtn
= !m_xResetBtn
->get_visible();
330 m_xOKBtn
->connect_clicked(LINK(this, SfxTabDialogController
, OkHdl
));
331 m_xCancelBtn
->connect_clicked(LINK(this, SfxTabDialogController
, CancelHdl
));
332 m_xResetBtn
->connect_clicked(LINK(this, SfxTabDialogController
, ResetHdl
));
333 m_xResetBtn
->set_label(SfxResId(STR_RESET
));
334 m_xTabCtrl
->connect_enter_page(LINK(this, SfxTabDialogController
, ActivatePageHdl
));
335 m_xTabCtrl
->connect_leave_page(LINK(this, SfxTabDialogController
, DeactivatePageHdl
));
336 m_xResetBtn
->set_help_id(HID_TABDLG_RESET_BTN
);
340 m_xBaseFmtBtn
->set_label(SfxResId(STR_STANDARD_SHORTCUT
));
341 m_xBaseFmtBtn
->connect_clicked(LINK(this, SfxTabDialogController
, BaseFmtHdl
));
342 m_xBaseFmtBtn
->set_help_id(HID_TABDLG_STANDARD_BTN
);
343 m_xBaseFmtBtn
->show();
347 m_xUserBtn
->connect_clicked(LINK(this, SfxTabDialogController
, UserHdl
));
351 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
352 m_pOutSet
.reset(new SfxItemSet(*m_pSet
->GetPool(), m_pSet
->GetRanges()));
355 // The reset functionality seems to be confusing to many; disable in LOK.
356 if (comphelper::LibreOfficeKit::isActive())
360 IMPL_LINK_NOARG(SfxTabDialogController
, OkHdl
, weld::Button
&, void)
364 Handler of the Ok-Buttons
365 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
366 Returns <DeactivateRC::LeavePage>, <SfxTabDialog::Ok()> is called
367 and the Dialog is ended.
371 if (PrepareLeaveCurrentPage())
372 m_xDialog
->response(Ok());
375 IMPL_LINK_NOARG(SfxTabDialogController
, UserHdl
, weld::Button
&, void)
379 Handler of the User-Buttons
380 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
381 returns this <DeactivateRC::LeavePage> and <SfxTabDialog::Ok()> is called.
382 Then the Dialog is ended with the Return value <SfxTabDialog::Ok()>
386 if (PrepareLeaveCurrentPage())
393 m_xDialog
->response(nRet
);
397 IMPL_LINK_NOARG(SfxTabDialogController
, CancelHdl
, weld::Button
&, void)
399 m_xDialog
->response(RET_CANCEL
);
402 IMPL_LINK_NOARG(SfxTabDialogController
, ResetHdl
, weld::Button
&, void)
406 Handler behind the reset button.
407 The Current Page is new initialized with their initial data, all the
408 settings that the user has made on this page are repealed.
412 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, m_xTabCtrl
->get_current_page_ident());
413 assert(pDataObject
&& "Id not known");
415 pDataObject
->xTabPage
->Reset(m_pSet
.get());
416 // Also reset relevant items of ExampleSet and OutSet to initial state
417 if (!pDataObject
->fnGetRanges
)
421 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
423 const SfxItemPool
* pPool
= m_pSet
->GetPool();
424 const WhichRangesContainer
& pTmpRanges
= (pDataObject
->fnGetRanges
)();
426 for (const auto & rPair
: pTmpRanges
)
428 // Correct Range with multiple values
429 sal_uInt16 nTmp
= rPair
.first
, nTmpEnd
= rPair
.second
;
430 DBG_ASSERT(nTmp
<= nTmpEnd
, "Range is sorted the wrong way");
434 // If really sorted wrongly, then set new
435 std::swap(nTmp
, nTmpEnd
);
438 while (nTmp
&& nTmp
<= nTmpEnd
)
440 // Iterate over the Range and set the Items
441 sal_uInt16 nWh
= pPool
->GetWhich(nTmp
);
442 const SfxPoolItem
* pItem
;
443 if (SfxItemState::SET
== m_pSet
->GetItemState(nWh
, false, &pItem
))
445 m_xExampleSet
->Put(*pItem
);
446 m_pOutSet
->Put(*pItem
);
450 m_xExampleSet
->ClearItem(nWh
);
451 m_pOutSet
->ClearItem(nWh
);
460 Handler behind the Standard-Button.
461 This button is available when editing style sheets. All the set attributes
462 in the edited stylesheet are deleted.
464 IMPL_LINK_NOARG(SfxTabDialogController
, BaseFmtHdl
, weld::Button
&, void)
466 m_bStandardPushed
= true;
468 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, m_xTabCtrl
->get_current_page_ident());
469 assert(pDataObject
&& "Id not known");
471 if (!pDataObject
->fnGetRanges
)
475 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
477 const SfxItemPool
* pPool
= m_pSet
->GetPool();
478 const WhichRangesContainer
& pTmpRanges
= (pDataObject
->fnGetRanges
)();
479 SfxItemSet
aTmpSet(*m_xExampleSet
);
481 for (const auto& rPair
: pTmpRanges
)
483 // Correct Range with multiple values
484 sal_uInt16 nTmp
= rPair
.first
, nTmpEnd
= rPair
.second
;
485 DBG_ASSERT( nTmp
<= nTmpEnd
, "Range is sorted the wrong way" );
487 if ( nTmp
> nTmpEnd
)
489 // If really sorted wrongly, then set new
490 std::swap(nTmp
, nTmpEnd
);
493 while ( nTmp
&& nTmp
<= nTmpEnd
) // guard against overflow
495 // Iterate over the Range and set the Items
496 sal_uInt16 nWh
= pPool
->GetWhich(nTmp
);
497 m_xExampleSet
->ClearItem(nWh
);
498 aTmpSet
.ClearItem(nWh
);
499 // At the Outset of InvalidateItem,
500 // so that the change takes effect
501 m_pOutSet
->InvalidateItem(nWh
);
505 // Set all Items as new -> the call the current Page Reset()
506 assert(pDataObject
->xTabPage
&& "the Page is gone");
507 pDataObject
->xTabPage
->Reset( &aTmpSet
);
508 pDataObject
->xTabPage
->pImpl
->mbStandard
= true;
511 IMPL_LINK(SfxTabDialogController
, ActivatePageHdl
, const OString
&, rPage
, void)
515 Handler that is called by StarView for switching to a different page.
516 If possible the <SfxTabPage::Reset(const SfxItemSet &)> or
517 <SfxTabPage::ActivatePage(const SfxItemSet &)> is called on the new page
521 assert(!m_pImpl
->aData
.empty() && "no Pages registered");
522 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, rPage
);
525 SAL_WARN("sfx.dialog", "Tab Page ID '" << rPage
<< "' not known, this is pretty serious and needs investigation");
529 SfxTabPage
* pTabPage
= pDataObject
->xTabPage
.get();
533 if (pDataObject
->bRefresh
)
534 pTabPage
->Reset(m_pSet
.get());
535 pDataObject
->bRefresh
= false;
538 pTabPage
->ActivatePage(*m_xExampleSet
);
540 if (pTabPage
->IsReadOnly() || m_pImpl
->bHideResetBtn
)
546 IMPL_LINK(SfxTabDialogController
, DeactivatePageHdl
, const OString
&, rPage
, bool)
550 Handler that is called by StarView before leaving a page.
554 <SfxTabPage::DeactivatePage(SfxItemSet *)>
558 assert(!m_pImpl
->aData
.empty() && "no Pages registered");
559 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, rPage
);
562 SAL_WARN("sfx.dialog", "Tab Page ID not known, this is pretty serious and needs investigation");
566 SfxTabPage
* pPage
= pDataObject
->xTabPage
.get();
570 DeactivateRC nRet
= DeactivateRC::LeavePage
;
572 if (!m_xExampleSet
&& pPage
->HasExchangeSupport() && m_pSet
)
573 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
->GetPool(), m_pSet
->GetRanges()));
577 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
579 if (pPage
->HasExchangeSupport())
580 nRet
= pPage
->DeactivatePage(&aTmp
);
582 nRet
= pPage
->DeactivatePage(nullptr);
583 if ( ( DeactivateRC::LeavePage
& nRet
) == DeactivateRC::LeavePage
&&
584 aTmp
.Count() && m_xExampleSet
)
586 m_xExampleSet
->Put( aTmp
);
587 m_pOutSet
->Put( aTmp
);
592 if ( pPage
->HasExchangeSupport() ) //!!!
596 SfxItemPool
* pPool
= pPage
->GetItemSet().GetPool();
597 m_xExampleSet
.reset(new SfxItemSet(*pPool
, GetInputRanges(*pPool
)));
599 nRet
= pPage
->DeactivatePage(m_xExampleSet
.get());
602 nRet
= pPage
->DeactivatePage( nullptr );
605 if ( nRet
& DeactivateRC::RefreshSet
)
608 // Flag all Pages as to be initialized as new
610 for (auto const& elem
: m_pImpl
->aData
)
612 elem
->bRefresh
= ( elem
->xTabPage
.get() != pPage
); // Do not refresh own Page anymore
615 return static_cast<bool>(nRet
& DeactivateRC::LeavePage
);
618 bool SfxTabDialogController::PrepareLeaveCurrentPage()
620 const OString sId
= m_xTabCtrl
->get_current_page_ident();
621 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, sId
);
622 DBG_ASSERT( pDataObject
, "Id not known" );
623 SfxTabPage
* pPage
= pDataObject
? pDataObject
->xTabPage
.get() : nullptr;
629 DeactivateRC nRet
= DeactivateRC::LeavePage
;
632 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
634 if ( pPage
->HasExchangeSupport() )
635 nRet
= pPage
->DeactivatePage( &aTmp
);
637 nRet
= pPage
->DeactivatePage( nullptr );
639 if ( ( DeactivateRC::LeavePage
& nRet
) == DeactivateRC::LeavePage
642 m_xExampleSet
->Put( aTmp
);
643 m_pOutSet
->Put( aTmp
);
647 nRet
= pPage
->DeactivatePage( nullptr );
648 bEnd
= nRet
!= DeactivateRC::KeepPage
;
654 const WhichRangesContainer
& SfxTabDialogController::GetInputRanges(const SfxItemPool
& rPool
)
658 Makes the set over the range of all pages of the dialogue. Pages have the
659 static method for querying their range in AddTabPage, ie deliver their
664 Pointer to a null-terminated array of sal_uInt16. This array belongs to the
665 dialog and is deleted when the dialogue is destroy.
669 <SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, bool)>
670 <SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)>
671 <SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)>
677 SAL_WARN( "sfx.dialog", "Set already exists!" );
678 return m_pSet
->GetRanges();
681 if ( !m_pRanges
.empty() )
683 SfxItemSet
aUS(const_cast<SfxItemPool
&>(rPool
));
685 for (auto const& elem
: m_pImpl
->aData
)
688 if ( elem
->fnGetRanges
)
690 const WhichRangesContainer
& pTmpRanges
= (elem
->fnGetRanges
)();
692 for (const auto & rPair
: pTmpRanges
)
694 sal_uInt16 nWidFrom
= rPool
.GetWhich(rPair
.first
);
695 sal_uInt16 nWidTo
= rPool
.GetWhich(rPair
.second
);
696 aUS
.MergeRange(nWidFrom
, nWidTo
); // Keep it valid
701 m_pRanges
= aUS
.GetRanges();
705 SfxTabDialogController::~SfxTabDialogController()
709 for (auto & elem
: m_pImpl
->aData
)
711 if ( elem
->xTabPage
)
713 // save settings of all pages (user data)
714 elem
->xTabPage
->FillUserData();
715 OUString
aPageData( elem
->xTabPage
->GetUserData() );
716 if ( !aPageData
.isEmpty() )
718 // save settings of all pages (user data)
719 OUString sConfigId
= OStringToOUString(elem
->xTabPage
->GetConfigId(),
720 RTL_TEXTENCODING_UTF8
);
721 SvtViewOptions
aPageOpt(EViewType::TabPage
, sConfigId
);
722 aPageOpt
.SetUserItem( USERITEM_NAME
, makeAny( aPageData
) );
725 elem
->xTabPage
.reset();
732 short SfxTabDialogController::Ok()
736 Ok handler for the Dialogue.
738 Dialog's current location and current page are saved for the next time
741 The OutputSet is created and for each page this or the special OutputSet
742 is set by calling the method <SfxTabPage::FillItemSet(SfxItemSet &)>, to
743 insert the entered data by the user into the set.
747 RET_OK: if at least one page has returned from FillItemSet,
748 otherwise RET_CANCEL.
751 SavePosAndId(); //See fdo#38828 "Apply" resetting window position
756 m_pOutSet
.reset(new SfxItemSet( *m_xExampleSet
));
758 m_pOutSet
= m_pSet
->Clone( false ); // without Items
760 bool bModified
= false;
762 for (auto const& elem
: m_pImpl
->aData
)
764 SfxTabPage
* pTabPage
= elem
->xTabPage
.get();
768 if ( m_pSet
&& !pTabPage
->HasExchangeSupport() )
770 SfxItemSet
aTmp( *m_pSet
->GetPool(), m_pSet
->GetRanges() );
772 if ( pTabPage
->FillItemSet( &aTmp
) )
776 m_xExampleSet
->Put( aTmp
);
777 m_pOutSet
->Put( aTmp
);
783 if (m_pOutSet
&& m_pOutSet
->Count() > 0)
786 if (m_bStandardPushed
)
789 return bModified
? RET_OK
: RET_CANCEL
;
792 void SfxTabDialogController::RefreshInputSet()
796 Default implementation of the virtual Method.
797 This is called, when <SfxTabPage::DeactivatePage(SfxItemSet *)>
798 returns <DeactivateRC::RefreshSet>.
802 SAL_INFO ( "sfx.dialog", "RefreshInputSet not implemented" );
805 void SfxTabDialogController::PageCreated
809 Default implementation of the virtual method. This is called immediately
810 after creating a page. Here the dialogue can call the TabPage Method
815 const OString
&, // Id of the created page
816 SfxTabPage
& // Reference to the created page
821 void SfxTabDialogController::SavePosAndId()
823 // save settings (screen position and current page)
824 SvtViewOptions
aDlgOpt(EViewType::TabDialog
, OStringToOUString(m_xDialog
->get_help_id(), RTL_TEXTENCODING_UTF8
));
825 aDlgOpt
.SetPageID(m_xTabCtrl
->get_current_page_ident());
829 Adds a page to the dialog. The Name must correspond to an entry in the
830 TabControl in the dialog .ui
832 void SfxTabDialogController::AddTabPage(const OString
&rName
/* Page ID */,
833 CreateTabPage pCreateFunc
/* Pointer to the Factory Method */,
834 GetTabPageRanges pRangesFunc
/* Pointer to the Method for querying Ranges onDemand */)
836 m_pImpl
->aData
.push_back(new Data_Impl(rName
, pCreateFunc
, pRangesFunc
));
839 void SfxTabDialogController::AddTabPage(const OString
&rName
/* Page ID */,
840 sal_uInt16 nPageCreateId
/* Identifier of the Factory Method to create the page */)
842 SfxAbstractDialogFactory
* pFact
= SfxAbstractDialogFactory::Create();
843 CreateTabPage pCreateFunc
= pFact
->GetTabPageCreatorFunc(nPageCreateId
);
844 GetTabPageRanges pRangesFunc
= pFact
->GetTabPageRangesFunc(nPageCreateId
);
845 AddTabPage(rName
, pCreateFunc
, pRangesFunc
);
850 Add a page to the dialog. The Rider text is passed on, the page has no
851 counterpart in the TabControl in the resource of the dialogue.
854 void SfxTabDialogController::AddTabPage(const OString
&rName
, /* Page ID */
855 const OUString
& rRiderText
,
856 CreateTabPage pCreateFunc
/* Pointer to the Factory Method */)
858 assert(!m_xTabCtrl
->get_page(rName
) && "Double Page-Ids in the Tabpage");
859 m_xTabCtrl
->append_page(rName
, rRiderText
);
860 AddTabPage(rName
, pCreateFunc
, nullptr);
863 void SfxTabDialogController::AddTabPage(const OString
&rName
, const OUString
& rRiderText
,
864 sal_uInt16 nPageCreateId
/* Identifier of the Factory Method to create the page */)
866 assert(!m_xTabCtrl
->get_page(rName
) && "Double Page-Ids in the Tabpage");
867 m_xTabCtrl
->append_page(rName
, rRiderText
);
868 AddTabPage(rName
, nPageCreateId
);
873 Default implementation of the virtual Method.
874 This is called when pages create their sets onDemand.
876 SfxItemSet
* SfxTabDialogController::CreateInputItemSet(const OString
&)
878 SAL_WARN( "sfx.dialog", "CreateInputItemSet not implemented" );
879 m_xItemSet
= std::make_unique
<SfxAllItemSet
>(SfxGetpApp()->GetPool());
880 return m_xItemSet
.get();
883 void SfxTabDialogController::CreatePages()
885 for (auto pDataObject
: m_pImpl
->aData
)
887 if (pDataObject
->xTabPage
)
889 weld::Container
* pPage
= m_xTabCtrl
->get_page(pDataObject
->sId
);
891 pDataObject
->xTabPage
= (pDataObject
->fnCreatePage
)(pPage
, this, m_pSet
.get());
893 pDataObject
->xTabPage
= (pDataObject
->fnCreatePage
)(pPage
, this, CreateInputItemSet(pDataObject
->sId
));
894 pDataObject
->xTabPage
->SetDialogController(this);
895 OUString sConfigId
= OStringToOUString(pDataObject
->xTabPage
->GetConfigId(), RTL_TEXTENCODING_UTF8
);
896 SvtViewOptions
aPageOpt(EViewType::TabPage
, sConfigId
);
898 Any aUserItem
= aPageOpt
.GetUserItem(USERITEM_NAME
);
900 if ( aUserItem
>>= aTemp
)
902 pDataObject
->xTabPage
->SetUserData(sUserData
);
904 PageCreated(pDataObject
->sId
, *pDataObject
->xTabPage
);
905 if (pDataObject
->xTabPage
->DeferResetToFirstActivation())
906 pDataObject
->bRefresh
= true; // Reset will be called in ActivatePageHdl
908 pDataObject
->xTabPage
->Reset(m_pSet
.get());
912 void SfxTabDialogController::setPreviewsToSamePlace()
914 //where tab pages have the same basic layout with a preview on the right,
915 //get both of their non-preview areas to request the same size so that the
916 //preview appears in the same place in each one so flipping between tabs
917 //isn't distracting as it jumps around
918 std::vector
<std::unique_ptr
<weld::Widget
>> aGrids
;
919 for (auto pDataObject
: m_pImpl
->aData
)
921 if (!pDataObject
->xTabPage
)
923 if (!pDataObject
->xTabPage
->m_xBuilder
)
925 std::unique_ptr
<weld::Widget
> pGrid
= pDataObject
->xTabPage
->m_xBuilder
->weld_widget("maingrid");
928 aGrids
.emplace_back(std::move(pGrid
));
931 m_xSizeGroup
.reset();
933 if (aGrids
.size() <= 1)
936 m_xSizeGroup
= m_xBuilder
->create_size_group();
937 m_xSizeGroup
->set_mode(VclSizeGroupMode::Both
);
938 for (auto& rGrid
: aGrids
)
939 m_xSizeGroup
->add_widget(rGrid
.get());
942 void SfxTabDialogController::RemoveTabPage(const OString
& rId
)
946 Delete the TabPage with ID nId
951 m_xTabCtrl
->remove_page(rId
);
952 Data_Impl
* pDataObject
= Find( m_pImpl
->aData
, rId
, &nPos
);
956 if ( pDataObject
->xTabPage
)
958 pDataObject
->xTabPage
->FillUserData();
959 OUString
aPageData( pDataObject
->xTabPage
->GetUserData() );
960 if ( !aPageData
.isEmpty() )
962 // save settings of this page (user data)
963 OUString sConfigId
= OStringToOUString(pDataObject
->xTabPage
->GetConfigId(),
964 RTL_TEXTENCODING_UTF8
);
965 SvtViewOptions
aPageOpt(EViewType::TabPage
, sConfigId
);
966 aPageOpt
.SetUserItem( USERITEM_NAME
, makeAny( aPageData
) );
969 pDataObject
->xTabPage
.reset();
973 m_pImpl
->aData
.erase( m_pImpl
->aData
.begin() + nPos
);
977 SAL_INFO( "sfx.dialog", "TabPage-Id not known" );
981 void SfxTabDialogController::Start_Impl()
985 setPreviewsToSamePlace();
987 assert(m_pImpl
->aData
.size() == static_cast<size_t>(m_xTabCtrl
->get_n_pages())
988 && "not all pages registered");
990 // load old settings, when exists, setting SetCurPageId will override the settings,
991 // something that the sort dialog in calc depends on
992 if (m_sAppPageId
.isEmpty())
994 SvtViewOptions
aDlgOpt(EViewType::TabDialog
, OStringToOUString(m_xDialog
->get_help_id(), RTL_TEXTENCODING_UTF8
));
995 if (aDlgOpt
.Exists())
996 m_xTabCtrl
->set_current_page(aDlgOpt
.GetPageID());
999 ActivatePageHdl(m_xTabCtrl
->get_current_page_ident());
1001 m_pImpl
->bStarted
= true;
1004 void SfxTabDialogController::SetCurPageId(const OString
& rIdent
)
1006 m_sAppPageId
= rIdent
;
1007 m_xTabCtrl
->set_current_page(m_sAppPageId
);
1012 The TabPage is activated with the specified Id.
1014 void SfxTabDialogController::ShowPage(const OString
& rIdent
)
1016 SetCurPageId(rIdent
);
1017 ActivatePageHdl(rIdent
);
1020 OString
SfxTabDialogController::GetCurPageId() const
1022 return m_xTabCtrl
->get_current_page_ident();
1025 short SfxTabDialogController::run()
1028 return SfxDialogController::run();
1031 bool SfxTabDialogController::runAsync(const std::shared_ptr
<SfxTabDialogController
>& rController
,
1032 const std::function
<void(sal_Int32
)>& rFunc
)
1034 rController
->Start_Impl();
1035 return weld::DialogController::runAsync(rController
, rFunc
);
1038 void SfxTabDialogController::SetInputSet( const SfxItemSet
* pInSet
)
1042 With this method the Input-Set can subsequently be set initially or re-set.
1046 bool bSet
= ( m_pSet
!= nullptr );
1047 m_pSet
.reset(pInSet
? new SfxItemSet(*pInSet
) : nullptr);
1049 if (!bSet
&& !m_xExampleSet
&& !m_pOutSet
&& m_pSet
)
1051 m_xExampleSet
.reset(new SfxItemSet(*m_pSet
));
1052 m_pOutSet
.reset(new SfxItemSet( *m_pSet
->GetPool(), m_pSet
->GetRanges() ));
1056 SfxItemSet
* SfxTabDialogController::GetInputSetImpl()
1060 Derived classes may create new storage for the InputSet. This has to be
1061 released in the Destructor. To do this, this method must be called.
1065 return m_pSet
.get();
1068 void SfxTabDialogController::RemoveResetButton()
1070 m_xResetBtn
->hide();
1071 m_pImpl
->bHideResetBtn
= true;
1074 void SfxTabDialogController::RemoveStandardButton()
1076 m_xBaseFmtBtn
->hide();
1079 SfxTabPage
* SfxTabDialogController::GetTabPage(std::string_view rPageId
) const
1083 Return TabPage with the specified Id.
1087 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, rPageId
);
1089 return pDataObject
->xTabPage
.get();
1093 void SfxTabDialogController::SetApplyHandler(const Link
<weld::Button
&, void>& _rHdl
)
1095 DBG_ASSERT( m_xApplyBtn
, "SfxTabDialog::GetApplyHandler: no apply button enabled!" );
1097 m_xApplyBtn
->connect_clicked(_rHdl
);
1100 bool SfxTabDialogController::Apply()
1102 bool bApplied
= false;
1103 if (PrepareLeaveCurrentPage())
1105 bApplied
= (Ok() == RET_OK
);
1106 //let the pages update their saved values
1107 GetInputSetImpl()->Put(*GetOutputItemSet());
1108 for (auto pDataObject
: m_pImpl
->aData
)
1110 if (!pDataObject
->xTabPage
)
1112 pDataObject
->xTabPage
->ChangesApplied();
1118 std::vector
<OString
> SfxTabDialogController::getAllPageUIXMLDescriptions() const
1120 int nPages
= m_xTabCtrl
->get_n_pages();
1121 std::vector
<OString
> aRet
;
1122 aRet
.reserve(nPages
);
1123 for (int i
= 0; i
< nPages
; ++i
)
1124 aRet
.push_back(m_xTabCtrl
->get_page_ident(i
));
1128 bool SfxTabDialogController::selectPageByUIXMLDescription(const OString
& rUIXMLDescription
)
1130 ShowPage(rUIXMLDescription
);
1131 return m_xTabCtrl
->get_current_page_ident() == rUIXMLDescription
;
1134 BitmapEx
SfxTabDialogController::createScreenshot() const
1136 // if we haven't run Start_Impl yet, do so now to create the initial pages
1137 if (!m_pImpl
->bStarted
)
1139 const_cast<SfxTabDialogController
*>(this)->Start_Impl();
1142 VclPtr
<VirtualDevice
> xDialogSurface(m_xDialog
->screenshot());
1143 return xDialogSurface
->GetBitmapEx(Point(), xDialogSurface
->GetOutputSizePixel());
1146 OString
SfxTabDialogController::GetScreenshotId() const
1148 const OString sId
= m_xTabCtrl
->get_current_page_ident();
1149 Data_Impl
* pDataObject
= Find(m_pImpl
->aData
, sId
);
1150 SfxTabPage
* pPage
= pDataObject
? pDataObject
->xTabPage
.get() : nullptr;
1153 OString
sHelpId(pPage
->GetHelpId());
1154 if (!sHelpId
.isEmpty())
1157 return m_xDialog
->get_help_id();
1160 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */