LibreOffice Module sfx2 (master) 1
tabdlg.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include <stdlib.h>
22#include <algorithm>
23#include <string_view>
24
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>
31#include <utility>
32#include <vcl/virdev.hxx>
33#include <sal/log.hxx>
34#include <tools/debug.hxx>
35#include <comphelper/lok.hxx>
36
37#include <sfx2/strings.hrc>
38#include <helpids.h>
39
40using namespace ::com::sun::star::uno;
41
42constexpr OUStringLiteral USERITEM_NAME = u"UserItem";
43
44
46{
49 css::uno::Reference< css::frame::XFrame > mxFrame;
50
52};
53
54namespace {
55
56struct Data_Impl
57{
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
63
64 // Constructor
65 Data_Impl( const OUString& rId, CreateTabPage fnPage,
66 GetTabPageRanges fnRanges ) :
67
68 sId ( rId ),
69 fnCreatePage( fnPage ),
70 fnGetRanges ( fnRanges ),
71 bRefresh ( false )
72 {
73 }
74};
75
76}
77
79 : SfxSetItem( rAttr, pItemPool )
80{
81}
82
83SfxTabDialogItem::SfxTabDialogItem( sal_uInt16 nId, const SfxItemSet& rItemSet )
84 : SfxSetItem( nId, rItemSet )
85{
86}
87
89{
90 return new SfxTabDialogItem( *this, pToPool );
91}
92
93typedef std::vector<Data_Impl*> SfxTabDlgData_Impl;
94
96{
97 bool bHideResetBtn : 1;
98 bool bStarted : 1;
100
101 explicit TabDlg_Impl(sal_uInt8 nCnt)
102 : bHideResetBtn(false)
103 , bStarted(false)
104 {
105 aData.reserve( nCnt );
106 }
107};
108
109static Data_Impl* Find( const SfxTabDlgData_Impl& rArr, std::u16string_view rId, sal_uInt16* pPos = nullptr)
110{
111 const sal_uInt16 nCount = rArr.size();
112
113 for ( sal_uInt16 i = 0; i < nCount; ++i )
114 {
115 Data_Impl* pObj = rArr[i];
116
117 if ( pObj->sId == rId )
118 {
119 if ( pPos )
120 *pPos = i;
121 return pObj;
122 }
123 }
124 return nullptr;
125}
126
127void SfxTabPage::SetFrame(const css::uno::Reference< css::frame::XFrame >& xFrame)
128{
129 if (mpImpl)
130 mpImpl->mxFrame = xFrame;
131}
132
133css::uno::Reference< css::frame::XFrame > SfxTabPage::GetFrame() const
134{
135 if (mpImpl)
136 return mpImpl->mxFrame;
137 return css::uno::Reference< css::frame::XFrame >();
138}
139
140SfxTabPage::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())
144 , mpSet(rAttrSet)
145 , mbHasExchangeSupport(false)
146 , mpImpl(new TabPageImpl)
147{
148 mpImpl->mpSfxDialogController = dynamic_cast<SfxOkDialogController*>(m_pDialogController);
149}
150
152{
153 if (m_xContainer)
154 {
155 std::unique_ptr<weld::Container> xParent(m_xContainer->weld_parent());
156 if (xParent)
157 xParent->move(m_xContainer.get(), nullptr);
158 }
159 m_xContainer.reset();
160 mpImpl.reset();
161 m_xBuilder.reset();
162}
163
165{
166 return false;
167}
168
170{
171}
172
174
176/* [Description]
177
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 *)>
181*/
182{
183}
184
186
187/* [Description]
188
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 &)>.
196
197 [Return value]
198
199 DeactivateRC::LeavePage; Allow leaving the page
200*/
201
202{
204}
205
206
208
209/* [Description]
210
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()>.
214*/
215
216{
217}
218
219
221{
222 return false;
223}
224
225
226const SfxPoolItem* SfxTabPage::GetItem( const SfxItemSet& rSet, sal_uInt16 nSlot, bool bDeep )
227
228/* [Description]
229
230 static Method: hereby are the implementations of the TabPage code
231 being simplified.
232*/
233
234{
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 );
239
240 if ( !pItem && nWh != nSlot )
241 pItem = &pPool->GetDefaultItem( nWh );
242 return pItem;
243}
244
245
247 sal_uInt16 nSlot, bool bDeep )
248
249/* [Description]
250
251 This method returns an attribute for comparison of the old value.
252*/
253
254{
255 const SfxItemSet& rOldSet = GetItemSet();
256 sal_uInt16 nWh = GetWhich( nSlot, bDeep );
257 const SfxPoolItem* pItem = nullptr;
258
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 );
264 else
265 pItem = GetItem( rOldSet, nSlot );
266 return pItem;
267}
268
270{
271 SAL_WARN( "sfx.dialog", "SfxTabPage::PageCreated should not be called");
272}
273
275{
276}
277
279{
280 mpImpl->mpSfxDialogController = pDialog;
281 m_pDialogController = mpImpl->mpSfxDialogController;
282}
283
285{
286 return mpImpl->mpSfxDialogController;
287}
288
289OUString SfxTabPage::GetHelpId() const
290{
291 if (m_xContainer)
292 return m_xContainer->get_help_id();
293 return {};
294}
295
297{
300 return nullptr;
301}
302
304{
305 if (mpImpl->mpSfxDialogController)
306 return mpImpl->mpSfxDialogController->GetExampleSet();
307 return nullptr;
308}
309
311(
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
317)
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)
328{
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);
338
339 if (bEditFmt)
340 {
341 m_xBaseFmtBtn->set_label(SfxResId(STR_STANDARD_SHORTCUT));
342 m_xBaseFmtBtn->connect_clicked(LINK(this, SfxTabDialogController, BaseFmtHdl));
344 m_xBaseFmtBtn->show();
345 }
346
347 if (m_xUserBtn)
348 m_xUserBtn->connect_clicked(LINK(this, SfxTabDialogController, UserHdl));
349
350 if (m_pSet)
351 {
352 m_xExampleSet.reset(new SfxItemSet(*m_pSet));
353 m_pOutSet.reset(new SfxItemSet(*m_pSet->GetPool(), m_pSet->GetRanges()));
354 }
355
356 // The reset functionality seems to be confusing to many; disable in LOK.
359}
360
362
363/* [Description]
364
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.
369*/
370
371{
372 if (PrepareLeaveCurrentPage())
373 m_xDialog->response(Ok());
374}
375
377
378/* [Description]
379
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()>
384*/
385
386{
387 if (PrepareLeaveCurrentPage())
388 {
389 short nRet = Ok();
390 if (RET_OK == nRet)
391 nRet = RET_USER;
392 else
393 nRet = RET_CANCEL;
394 m_xDialog->response(nRet);
395 }
396}
397
399{
400 m_xDialog->response(RET_CANCEL);
401}
402
404
405/* [Description]
406
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.
410*/
411
412{
413 Data_Impl* pDataObject = Find(m_pImpl->aData, m_xTabCtrl->get_current_page_ident());
414 assert(pDataObject && "Id not known");
415
416 pDataObject->xTabPage->Reset(m_pSet.get());
417 // Also reset relevant items of ExampleSet and OutSet to initial state
418 if (!pDataObject->fnGetRanges)
419 return;
420
421 if (!m_xExampleSet)
422 m_xExampleSet.reset(new SfxItemSet(*m_pSet));
423
424 const SfxItemPool* pPool = m_pSet->GetPool();
425 const WhichRangesContainer& pTmpRanges = (pDataObject->fnGetRanges)();
426
427 for (const auto & rPair : pTmpRanges)
428 {
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");
432
433 if (nTmp > nTmpEnd)
434 {
435 // If really sorted wrongly, then set new
436 std::swap(nTmp, nTmpEnd);
437 }
438
439 while (nTmp && nTmp <= nTmpEnd)
440 {
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))
445 {
446 m_xExampleSet->Put(*pItem);
447 m_pOutSet->Put(*pItem);
448 }
449 else
450 {
451 m_xExampleSet->ClearItem(nWh);
452 m_pOutSet->ClearItem(nWh);
453 }
454 nTmp++;
455 }
456 }
457}
458
459/* [Description]
460
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.
464*/
466{
467 m_bStandardPushed = true;
468
469 Data_Impl* pDataObject = Find(m_pImpl->aData, m_xTabCtrl->get_current_page_ident());
470 assert(pDataObject && "Id not known");
471
472 if (!pDataObject->fnGetRanges)
473 return;
474
475 if (!m_xExampleSet)
476 m_xExampleSet.reset(new SfxItemSet(*m_pSet));
477
478 const SfxItemPool* pPool = m_pSet->GetPool();
479 const WhichRangesContainer& pTmpRanges = (pDataObject->fnGetRanges)();
480 SfxItemSet aTmpSet(*m_xExampleSet);
481
482 for (const auto& rPair : pTmpRanges)
483 {
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" );
487
488 if ( nTmp > nTmpEnd )
489 {
490 // If really sorted wrongly, then set new
491 std::swap(nTmp, nTmpEnd);
492 }
493
494 while ( nTmp && nTmp <= nTmpEnd ) // guard against overflow
495 {
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);
503 nTmp++;
504 }
505 }
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;
510}
511
512IMPL_LINK(SfxTabDialogController, ActivatePageHdl, const OUString&, rPage, void)
513{
514 ActivatePage(rPage);
515}
516
517void SfxTabDialogController::ActivatePage(const OUString& rPage)
518/* [Description]
519
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
523*/
524
525{
526 assert(!m_pImpl->aData.empty() && "no Pages registered");
527 Data_Impl* pDataObject = Find(m_pImpl->aData, rPage);
528 if (!pDataObject)
529 {
530 SAL_WARN("sfx.dialog", "Tab Page ID '" << rPage << "' not known, this is pretty serious and needs investigation");
531 return;
532 }
533
534 SfxTabPage* pTabPage = pDataObject->xTabPage.get();
535 if (!pTabPage)
536 return;
537
538 if (pDataObject->bRefresh)
539 pTabPage->Reset(m_pSet.get());
540 pDataObject->bRefresh = false;
541
542 if (m_xExampleSet)
543 pTabPage->ActivatePage(*m_xExampleSet);
544
545 if (pTabPage->IsReadOnly() || m_pImpl->bHideResetBtn)
546 m_xResetBtn->hide();
547 else
548 m_xResetBtn->show();
549}
550
551IMPL_LINK(SfxTabDialogController, DeactivatePageHdl, const OUString&, rPage, bool)
552{
553 return DeactivatePage(rPage);
554}
555
556bool SfxTabDialogController::DeactivatePage(std::u16string_view aPage)
557/* [Description]
558
559 Handler that is called by StarView before leaving a page.
560
561 [Cross-reference]
562
563 <SfxTabPage::DeactivatePage(SfxItemSet *)>
564*/
565
566{
567 assert(!m_pImpl->aData.empty() && "no Pages registered");
568 Data_Impl* pDataObject = Find(m_pImpl->aData, aPage);
569 if (!pDataObject)
570 {
571 SAL_WARN("sfx.dialog", "Tab Page ID not known, this is pretty serious and needs investigation");
572 return false;
573 }
574
575 SfxTabPage* pPage = pDataObject->xTabPage.get();
576 if (!pPage)
577 return true;
578
580
581 if (!m_xExampleSet && pPage->HasExchangeSupport() && m_pSet)
582 m_xExampleSet.reset(new SfxItemSet(*m_pSet->GetPool(), m_pSet->GetRanges()));
583
584 if (m_pSet)
585 {
586 SfxItemSet aTmp( *m_pSet->GetPool(), m_pSet->GetRanges() );
587
588 if (pPage->HasExchangeSupport())
589 nRet = pPage->DeactivatePage(&aTmp);
590 else
591 nRet = pPage->DeactivatePage(nullptr);
593 aTmp.Count() && m_xExampleSet)
594 {
595 m_xExampleSet->Put( aTmp );
596 m_pOutSet->Put( aTmp );
597 }
598 }
599 else
600 {
601 if ( pPage->HasExchangeSupport() )
602 {
603 if (!m_xExampleSet)
604 {
605 SfxItemPool* pPool = pPage->GetItemSet().GetPool();
606 m_xExampleSet.reset(new SfxItemSet(*pPool, GetInputRanges(*pPool)));
607 }
608 nRet = pPage->DeactivatePage(m_xExampleSet.get());
609 }
610 else
611 nRet = pPage->DeactivatePage( nullptr );
612 }
613
614 if ( nRet & DeactivateRC::RefreshSet )
615 {
617 // Flag all Pages as to be initialized as new
618
619 for (auto const& elem : m_pImpl->aData)
620 {
621 elem->bRefresh = ( elem->xTabPage.get() != pPage ); // Do not refresh own Page anymore
622 }
623 }
624 return static_cast<bool>(nRet & DeactivateRC::LeavePage);
625}
626
628{
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;
633
634 bool bEnd = !pPage;
635
636 if ( pPage )
637 {
639 if ( m_pSet )
640 {
641 SfxItemSet aTmp( *m_pSet->GetPool(), m_pSet->GetRanges() );
642
643 if ( pPage->HasExchangeSupport() )
644 nRet = pPage->DeactivatePage( &aTmp );
645 else
646 nRet = pPage->DeactivatePage( nullptr );
647
649 && aTmp.Count() )
650 {
651 m_xExampleSet->Put( aTmp );
652 m_pOutSet->Put( aTmp );
653 }
654 }
655 else
656 nRet = pPage->DeactivatePage( nullptr );
657 bEnd = nRet != DeactivateRC::KeepPage;
658 }
659
660 return bEnd;
661}
662
664
665/* [Description]
666
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
669 sets onDemand.
670
671 [Return value]
672
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.
675
676 [Cross-reference]
677
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)>
681*/
682
683{
684 if ( m_pSet )
685 {
686 SAL_WARN( "sfx.dialog", "Set already exists!" );
687 return m_pSet->GetRanges();
688 }
689
690 if ( !m_pRanges.empty() )
691 return m_pRanges;
692 SfxItemSet aUS(const_cast<SfxItemPool&>(rPool));
693
694 for (auto const& elem : m_pImpl->aData)
695 {
696
697 if ( elem->fnGetRanges )
698 {
699 const WhichRangesContainer& pTmpRanges = (elem->fnGetRanges)();
700
701 for (const auto & rPair : pTmpRanges)
702 {
703 sal_uInt16 nWidFrom = rPool.GetWhich(rPair.first);
704 sal_uInt16 nWidTo = rPool.GetWhich(rPair.second);
705 aUS.MergeRange(nWidFrom, nWidTo); // Keep it valid
706 }
707 }
708 }
709
710 m_pRanges = aUS.GetRanges();
711 return m_pRanges;
712}
713
715{
716 SavePosAndId();
717
718 for (auto & elem : m_pImpl->aData)
719 {
720 if ( elem->xTabPage )
721 {
722 // save settings of all pages (user data)
723 elem->xTabPage->FillUserData();
724 OUString aPageData( elem->xTabPage->GetUserData() );
725 if ( !aPageData.isEmpty() )
726 {
727 // save settings of all pages (user data)
728 SvtViewOptions aPageOpt(EViewType::TabPage, elem->xTabPage->GetConfigId());
729 aPageOpt.SetUserItem( USERITEM_NAME, Any( aPageData ) );
730 }
731
732 elem->xTabPage.reset();
733 }
734 delete elem;
735 elem = nullptr;
736 }
737}
738
740
741/* [Description]
742
743 Ok handler for the Dialogue.
744
745 Dialog's current location and current page are saved for the next time
746 the dialog is shown.
747
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.
751
752 [Return value]
753
754 RET_OK: if at least one page has returned from FillItemSet,
755 otherwise RET_CANCEL.
756*/
757{
758 SavePosAndId(); //See fdo#38828 "Apply" resetting window position
759
760 if ( !m_pOutSet )
761 {
762 if ( m_xExampleSet )
763 m_pOutSet.reset(new SfxItemSet( *m_xExampleSet ));
764 else if ( m_pSet )
765 m_pOutSet = m_pSet->Clone( false ); // without Items
766 }
767 bool bModified = false;
768
769 for (auto const& elem : m_pImpl->aData)
770 {
771 SfxTabPage* pTabPage = elem->xTabPage.get();
772
773 if ( pTabPage )
774 {
775 if ( m_pSet && !pTabPage->HasExchangeSupport() )
776 {
777 SfxItemSet aTmp( *m_pSet->GetPool(), m_pSet->GetRanges() );
778
779 if ( pTabPage->FillItemSet( &aTmp ) )
780 {
781 bModified = true;
782 if (m_xExampleSet)
783 m_xExampleSet->Put( aTmp );
784 m_pOutSet->Put( aTmp );
785 }
786 }
787 }
788 }
789
790 if (m_pOutSet && m_pOutSet->Count() > 0)
791 bModified = true;
792
794 bModified = true;
795
796 return bModified ? RET_OK : RET_CANCEL;
797}
798
800
801/* [Description]
802
803 Default implementation of the virtual Method.
804 This is called, when <SfxTabPage::DeactivatePage(SfxItemSet *)>
805 returns <DeactivateRC::RefreshSet>.
806*/
807
808{
809 SAL_INFO ( "sfx.dialog", "RefreshInputSet not implemented" );
810}
811
813
814/* [Description]
815
816 Default implementation of the virtual method. This is called immediately
817 after creating a page. Here the dialogue can call the TabPage Method
818 directly.
819*/
820
821(
822 const OUString&, // Id of the created page
823 SfxTabPage& // Reference to the created page
824)
825{
826}
827
829{
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());
833}
834
835/*
836 Adds a page to the dialog. The Name must correspond to an entry in the
837 TabControl in the dialog .ui
838*/
839void 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 */)
842{
843 m_pImpl->aData.push_back(new Data_Impl(rName, pCreateFunc, pRangesFunc));
844}
845
846void SfxTabDialogController::AddTabPage(const OUString &rName /* Page ID */,
847 sal_uInt16 nPageCreateId /* Identifier of the Factory Method to create the page */)
848{
850 CreateTabPage pCreateFunc = pFact->GetTabPageCreatorFunc(nPageCreateId);
851 GetTabPageRanges pRangesFunc = pFact->GetTabPageRangesFunc(nPageCreateId);
852 AddTabPage(rName, pCreateFunc, pRangesFunc);
853}
854
855/* [Description]
856
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.
859*/
860
861void SfxTabDialogController::AddTabPage(const OUString &rName, /* Page ID */
862 const OUString& rRiderText,
863 CreateTabPage pCreateFunc /* Pointer to the Factory Method */)
864{
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);
868}
869
870void SfxTabDialogController::AddTabPage(const OUString &rName, const OUString& rRiderText,
871 sal_uInt16 nPageCreateId /* Identifier of the Factory Method to create the page */)
872{
873 assert(!m_xTabCtrl->get_page(rName) && "Double Page-Ids in the Tabpage");
874 m_xTabCtrl->append_page(rName, rRiderText);
875 AddTabPage(rName, nPageCreateId);
876}
877
878/* [Description]
879
880 Default implementation of the virtual Method.
881 This is called when pages create their sets onDemand.
882*/
884{
885 SAL_WARN( "sfx.dialog", "CreateInputItemSet not implemented" );
886 m_xItemSet = std::make_unique<SfxAllItemSet>(SfxGetpApp()->GetPool());
887 return m_xItemSet.get();
888}
889
891{
892 for (auto pDataObject : m_pImpl->aData)
893 {
894 if (pDataObject->xTabPage)
895 continue;
896 weld::Container* pPage = m_xTabCtrl->get_page(pDataObject->sId);
897 if (m_pSet)
898 pDataObject->xTabPage = (pDataObject->fnCreatePage)(pPage, this, m_pSet.get());
899 else
900 pDataObject->xTabPage = (pDataObject->fnCreatePage)(pPage, this, CreateInputItemSet(pDataObject->sId));
901 pDataObject->xTabPage->SetDialogController(this);
902 SvtViewOptions aPageOpt(EViewType::TabPage, pDataObject->xTabPage->GetConfigId());
903 OUString sUserData;
904 Any aUserItem = aPageOpt.GetUserItem(USERITEM_NAME);
905 OUString aTemp;
906 if ( aUserItem >>= aTemp )
907 sUserData = aTemp;
908 pDataObject->xTabPage->SetUserData(sUserData);
909
910 PageCreated(pDataObject->sId, *pDataObject->xTabPage);
911 if (pDataObject->xTabPage->DeferResetToFirstActivation())
912 pDataObject->bRefresh = true; // Reset will be called in ActivatePageHdl
913 else
914 pDataObject->xTabPage->Reset(m_pSet.get());
915 }
916}
917
919{
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)
926 {
927 if (!pDataObject->xTabPage)
928 continue;
929 if (!pDataObject->xTabPage->m_xBuilder)
930 continue;
931 std::unique_ptr<weld::Widget> pGrid = pDataObject->xTabPage->m_xBuilder->weld_widget("maingrid");
932 if (!pGrid)
933 continue;
934 aGrids.emplace_back(std::move(pGrid));
935 }
936
937 m_xSizeGroup.reset();
938
939 if (aGrids.size() <= 1)
940 return;
941
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());
946}
947
948void SfxTabDialogController::RemoveTabPage(const OUString& rId)
949
950/* [Description]
951
952 Delete the TabPage with ID nId
953*/
954
955{
956 sal_uInt16 nPos = 0;
957 m_xTabCtrl->remove_page(rId);
958 Data_Impl* pDataObject = Find( m_pImpl->aData, rId, &nPos );
959
960 if ( pDataObject )
961 {
962 if ( pDataObject->xTabPage )
963 {
964 pDataObject->xTabPage->FillUserData();
965 OUString aPageData( pDataObject->xTabPage->GetUserData() );
966 if ( !aPageData.isEmpty() )
967 {
968 // save settings of this page (user data)
969 SvtViewOptions aPageOpt(EViewType::TabPage, pDataObject->xTabPage->GetConfigId());
970 aPageOpt.SetUserItem( USERITEM_NAME, Any( aPageData ) );
971 }
972
973 pDataObject->xTabPage.reset();
974 }
975
976 delete pDataObject;
977 m_pImpl->aData.erase( m_pImpl->aData.begin() + nPos );
978 }
979 else
980 {
981 SAL_INFO( "sfx.dialog", "TabPage-Id not known" );
982 }
983}
984
986{
987 CreatePages();
988
990
991 assert(m_pImpl->aData.size() == static_cast<size_t>(m_xTabCtrl->get_n_pages())
992 && "not all pages registered");
993
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())
997 {
998 SvtViewOptions aDlgOpt(EViewType::TabDialog, m_xDialog->get_help_id());
999 if (aDlgOpt.Exists())
1000 m_xTabCtrl->set_current_page(aDlgOpt.GetPageID());
1001 }
1002
1003 ActivatePage(m_xTabCtrl->get_current_page_ident());
1004
1005 m_pImpl->bStarted = true;
1006}
1007
1008void SfxTabDialogController::SetCurPageId(const OUString& rIdent)
1009{
1010 m_sAppPageId = rIdent;
1011 m_xTabCtrl->set_current_page(m_sAppPageId);
1012}
1013
1014/* [Description]
1015
1016 The TabPage is activated with the specified Id.
1017*/
1018void SfxTabDialogController::ShowPage(const OUString& rIdent)
1019{
1020 SetCurPageId(rIdent);
1021 ActivatePage(rIdent);
1022}
1023
1025{
1026 return m_xTabCtrl->get_current_page_ident();
1027}
1028
1030{
1031 Start_Impl();
1032 return SfxDialogController::run();
1033}
1034
1035bool SfxTabDialogController::runAsync(const std::shared_ptr<SfxTabDialogController>& rController,
1036 const std::function<void(sal_Int32)>& rFunc)
1037{
1038 rController->Start_Impl();
1039 return weld::DialogController::runAsync(rController, rFunc);
1040}
1041
1043
1044/* [Description]
1045
1046 With this method the Input-Set can subsequently be set initially or re-set.
1047*/
1048
1049{
1050 bool bSet = ( m_pSet != nullptr );
1051 m_pSet.reset(pInSet ? new SfxItemSet(*pInSet) : nullptr);
1052
1053 if (!bSet && !m_xExampleSet && !m_pOutSet && m_pSet)
1054 {
1055 m_xExampleSet.reset(new SfxItemSet(*m_pSet));
1056 m_pOutSet.reset(new SfxItemSet( *m_pSet->GetPool(), m_pSet->GetRanges() ));
1057 }
1058}
1059
1061
1062/* [Description]
1063
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.
1066*/
1067
1068{
1069 return m_pSet.get();
1070}
1071
1073{
1074 m_xResetBtn->hide();
1075 m_pImpl->bHideResetBtn = true;
1076}
1077
1079{
1080 m_xBaseFmtBtn->hide();
1081}
1082
1083SfxTabPage* SfxTabDialogController::GetTabPage(std::u16string_view rPageId) const
1084
1085/* [Description]
1086
1087 Return TabPage with the specified Id.
1088*/
1089
1090{
1091 Data_Impl* pDataObject = Find(m_pImpl->aData, rPageId);
1092 if (pDataObject)
1093 return pDataObject->xTabPage.get();
1094 return nullptr;
1095}
1096
1098{
1099 DBG_ASSERT( m_xApplyBtn, "SfxTabDialog::GetApplyHandler: no apply button enabled!" );
1100 if (m_xApplyBtn)
1101 m_xApplyBtn->connect_clicked(_rHdl);
1102}
1103
1105{
1106 bool bApplied = false;
1108 {
1109 bApplied = (Ok() == RET_OK);
1110 //let the pages update their saved values
1112 for (auto pDataObject : m_pImpl->aData)
1113 {
1114 if (!pDataObject->xTabPage)
1115 continue;
1116 pDataObject->xTabPage->ChangesApplied();
1117 }
1118 }
1119 return bApplied;
1120}
1121
1122std::vector<OUString> SfxTabDialogController::getAllPageUIXMLDescriptions() const
1123{
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));
1129 return aRet;
1130}
1131
1132bool SfxTabDialogController::selectPageByUIXMLDescription(const OUString& rUIXMLDescription)
1133{
1134 ShowPage(rUIXMLDescription);
1135 return m_xTabCtrl->get_current_page_ident() == rUIXMLDescription;
1136}
1137
1139{
1140 // if we haven't run Start_Impl yet, do so now to create the initial pages
1141 if (!m_pImpl->bStarted)
1142 {
1143 const_cast<SfxTabDialogController*>(this)->Start_Impl();
1144 }
1145
1146 VclPtr<VirtualDevice> xDialogSurface(m_xDialog->screenshot());
1147 return xDialogSurface->GetBitmapEx(Point(), xDialogSurface->GetOutputSizePixel());
1148}
1149
1151{
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;
1155 if (pPage)
1156 {
1157 OUString sHelpId(pPage->GetHelpId());
1158 if (!sHelpId.isEmpty())
1159 return sHelpId;
1160 }
1161 return m_xDialog->get_help_id();
1162}
1163
1164/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
SfxApplication * SfxGetpApp()
Definition: app.hxx:231
IMPL_LINK(SfxEventAsyncer_Impl, IdleHdl, Timer *, pAsyncIdle, void)
Definition: appcfg.cxx:96
Reference< XExecutableDialog > m_xDialog
WhichRangesContainer(* GetTabPageRanges)()
Definition: basedlgs.hxx:85
std::unique_ptr< weld::Builder > m_xBuilder
weld::DialogController * m_pDialogController
std::unique_ptr< weld::Container > m_xContainer
virtual GetTabPageRanges GetTabPageRangesFunc(sal_uInt16 nId)=0
static SfxAbstractDialogFactory * Create()
Definition: sfxdlg.cxx:22
virtual CreateTabPage GetTabPageCreatorFunc(sal_uInt16 nId)=0
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
const SfxPoolItem & GetDefaultItem(sal_uInt16 nWhich) const
SfxItemPool * GetPool() const
const SfxItemSet * GetParent() const
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
std::unique_ptr< SfxItemSet > m_pSet
Definition: tabdlg.hxx:77
virtual short Ok()
bool PrepareLeaveCurrentPage()
prepare to leave the current page.
OUString m_sAppPageId
Definition: tabdlg.hxx:81
SfxTabPage * GetTabPage(std::u16string_view rPageId) const
void SetCurPageId(const OUString &rName)
OUString GetCurPageId() const
void AddTabPage(const OUString &rName, CreateTabPage pCreateFunc, GetTabPageRanges pRangesFunc)
void SetInputSet(const SfxItemSet *pInSet)
std::unique_ptr< TabDlg_Impl > m_pImpl
Definition: tabdlg.hxx:79
void SavePosAndId()
save the position of the TabDialog and which tab page is the currently active one
std::unique_ptr< weld::Button > m_xCancelBtn
Definition: tabdlg.hxx:72
SfxTabDialogController(weld::Widget *pParent, const OUString &rUIXMLDescription, const OUString &rID, const SfxItemSet *=nullptr, bool bEditFmt=false)
Definition: tabdlg.cxx:311
SAL_DLLPRIVATE void Start_Impl()
std::unique_ptr< weld::Button > m_xResetBtn
Definition: tabdlg.hxx:73
std::unique_ptr< SfxItemSet > m_pOutSet
Definition: tabdlg.hxx:78
void RemoveTabPage(const OUString &rName)
std::unique_ptr< SfxAllItemSet > m_xItemSet
Definition: tabdlg.hxx:83
std::unique_ptr< weld::Button > m_xUserBtn
Definition: tabdlg.hxx:71
virtual short run() override
std::unique_ptr< SfxItemSet > m_xExampleSet
Definition: tabdlg.hxx:100
OUString GetScreenshotId() const
std::unique_ptr< weld::Button > m_xBaseFmtBtn
Definition: tabdlg.hxx:74
WhichRangesContainer m_pRanges
Definition: tabdlg.hxx:80
std::unique_ptr< weld::Notebook > m_xTabCtrl
Definition: tabdlg.hxx:61
virtual void ActivatePage(const OUString &rPage)
std::unique_ptr< weld::Button > m_xOKBtn
Definition: tabdlg.hxx:69
virtual SfxItemSet * CreateInputItemSet(const OUString &rName)
virtual void PageCreated(const OUString &rName, SfxTabPage &rPage)
SAL_DLLPRIVATE void setPreviewsToSamePlace()
virtual void RefreshInputSet()
std::vector< OUString > getAllPageUIXMLDescriptions() const
void SetApplyHandler(const Link< weld::Button &, void > &_rHdl)
const SfxItemSet * GetOutputItemSet() const
Definition: tabdlg.hxx:143
BitmapEx createScreenshot() const
void ShowPage(const OUString &rName)
std::unique_ptr< weld::Button > m_xApplyBtn
Definition: tabdlg.hxx:70
const WhichRangesContainer & GetInputRanges(const SfxItemPool &)
std::unique_ptr< weld::SizeGroup > m_xSizeGroup
Definition: tabdlg.hxx:75
SAL_DLLPRIVATE void CreatePages()
static bool runAsync(const std::shared_ptr< SfxTabDialogController > &rController, const std::function< void(sal_Int32)> &)
SfxItemSet * GetInputSetImpl()
virtual ~SfxTabDialogController() override
bool selectPageByUIXMLDescription(const OUString &rUIXMLDescription)
bool DeactivatePage(std::u16string_view aPage)
virtual SfxTabDialogItem * Clone(SfxItemPool *pToPool=nullptr) const override
Definition: tabdlg.cxx:88
SfxTabDialogItem(sal_uInt16 nId, const SfxItemSet &rItemSet)
Definition: tabdlg.cxx:83
bool HasExchangeSupport() const
Definition: tabdlg.hxx:238
virtual void Reset(const SfxItemSet *)
Definition: tabdlg.cxx:169
SfxTabPage(weld::Container *pPage, weld::DialogController *pController, const OUString &rUIXMLDescription, const OUString &rID, const SfxItemSet *rAttrSet)
Definition: tabdlg.cxx:140
void SetDialogController(SfxOkDialogController *pDialog)
Definition: tabdlg.cxx:278
virtual void FillUserData()
Definition: tabdlg.cxx:207
virtual bool DeferResetToFirstActivation()
Definition: tabdlg.cxx:173
std::unique_ptr< TabPageImpl > mpImpl
Definition: tabdlg.hxx:196
virtual void PageCreated(const SfxAllItemSet &aSet)
Definition: tabdlg.cxx:269
virtual ~SfxTabPage() override
Definition: tabdlg.cxx:151
const SfxItemSet & GetItemSet() const
Definition: tabdlg.hxx:228
SfxOkDialogController * GetDialogController() const
Definition: tabdlg.cxx:284
css::uno::Reference< css::frame::XFrame > GetFrame() const
Definition: tabdlg.cxx:133
virtual DeactivateRC DeactivatePage(SfxItemSet *pSet)
Definition: tabdlg.cxx:185
const SfxItemSet * GetDialogExampleSet() const
Definition: tabdlg.cxx:303
virtual bool FillItemSet(SfxItemSet *)
Definition: tabdlg.cxx:164
virtual bool IsReadOnly() const
Definition: tabdlg.cxx:220
void SetFrame(const css::uno::Reference< css::frame::XFrame > &xFrame)
Definition: tabdlg.cxx:127
virtual void ChangesApplied()
Definition: tabdlg.cxx:274
static const SfxPoolItem * GetItem(const SfxItemSet &rSet, sal_uInt16 nSlot, bool bDeep=true)
Definition: tabdlg.cxx:226
const SfxPoolItem * GetOldItem(const SfxItemSet &rSet, sal_uInt16 nSlot, bool bDeep=true)
Definition: tabdlg.cxx:246
weld::Window * GetFrameWeld() const
Definition: tabdlg.cxx:296
virtual void ActivatePage(const SfxItemSet &)
Definition: tabdlg.cxx:175
OUString GetHelpId() const
Definition: tabdlg.cxx:289
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
Definition: tabdlg.hxx:201
One SfxViewShell more or less represents one edit window for a document, there can be multiple ones f...
Definition: viewsh.hxx:165
virtual short run()
static bool runAsync(const std::shared_ptr< DialogController > &rController, const std::function< void(sal_Int32)> &)
virtual Dialog * getDialog()=0
std::shared_ptr< weld::Dialog > m_xDialog
std::unique_ptr< weld::Builder > m_xBuilder
int nCount
#define DBG_ASSERT(sCon, aError)
float u
IMPL_LINK_NOARG(SvFileObject, LoadGrfReady_Impl, void *, void)
Definition: fileobj.cxx:322
constexpr OUStringLiteral HID_TABDLG_RESET_BTN
Definition: helpids.h:30
constexpr OUStringLiteral HID_TABDLG_STANDARD_BTN
Definition: helpids.h:31
sal_uInt16 nPos
Definition: linksrc.cxx:118
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
bool isActive()
int i
sal_Int16 nId
OUString SfxResId(TranslateId aId)
Definition: sfxresid.cxx:22
static SfxItemSet & rSet
Definition: shell.cxx:534
bool bHideResetBtn
Definition: tabdlg.cxx:97
bool bStarted
Definition: tabdlg.cxx:98
SfxTabDlgData_Impl aData
Definition: tabdlg.cxx:99
TabDlg_Impl(sal_uInt8 nCnt)
Definition: tabdlg.cxx:101
css::uno::Reference< css::frame::XFrame > mxFrame
Definition: tabdlg.cxx:49
TabPageImpl()
Definition: tabdlg.cxx:51
bool mbStandard
Definition: tabdlg.cxx:47
SfxOkDialogController * mpSfxDialogController
Definition: tabdlg.cxx:48
bool empty() const noexcept
Reference< XFrame > xFrame
std::vector< Data_Impl * > SfxTabDlgData_Impl
Definition: tabdlg.cxx:93
constexpr OUStringLiteral USERITEM_NAME
Definition: tabdlg.cxx:42
static Data_Impl * Find(const SfxTabDlgData_Impl &rArr, std::u16string_view rId, sal_uInt16 *pPos=nullptr)
Definition: tabdlg.cxx:109
std::unique_ptr< SfxTabPage >(* CreateTabPage)(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet *rAttrSet)
Definition: tabdlg.hxx:39
DeactivateRC
Definition: tabdlg.hxx:173
#define RET_USER
Definition: tabdlg.hxx:47
unsigned char sal_uInt8
OUString sId
RET_OK
RET_CANCEL