bump product version to 5.0.4.1
[LibreOffice.git] / sfx2 / source / dialog / tabdlg.cxx
blob3cf58699652846e1ecde15f97dfd81c4ac52639f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <limits.h>
22 #include <stdlib.h>
23 #include <algorithm>
24 #include <vcl/builder.hxx>
25 #include <vcl/msgbox.hxx>
26 #include <unotools/viewoptions.hxx>
28 #include "appdata.hxx"
29 #include "sfxtypes.hxx"
30 #include <sfx2/tabdlg.hxx>
31 #include <sfx2/viewfrm.hxx>
32 #include <sfx2/app.hxx>
33 #include <sfx2/sfxresid.hxx>
34 #include <sfx2/sfxhelp.hxx>
35 #include <sfx2/ctrlitem.hxx>
36 #include <sfx2/bindings.hxx>
37 #include <sfx2/sfxdlg.hxx>
38 #include <sfx2/itemconnect.hxx>
40 #include "dialog.hrc"
41 #include "helpid.hrc"
43 using namespace ::com::sun::star::uno;
45 #define USERITEM_NAME OUString("UserItem")
47 TYPEINIT1(SfxTabDialogItem,SfxSetItem);
49 struct TabPageImpl
51 bool mbStandard;
52 sfx::ItemConnectionArray maItemConn;
53 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;
55 TabPageImpl() : mbStandard( false ) {}
58 struct Data_Impl
60 sal_uInt16 nId; // The ID
61 CreateTabPage fnCreatePage; // Pointer to Factory
62 GetTabPageRanges fnGetRanges; // Pointer to Ranges-Function
63 VclPtr<SfxTabPage> pTabPage; // The TabPage itself
64 bool bOnDemand; // Flag: ItemSet onDemand
65 bool bRefresh; // Flag: Page must be re-initialized
67 // Constructor
68 Data_Impl( sal_uInt16 Id, CreateTabPage fnPage,
69 GetTabPageRanges fnRanges, bool bDemand ) :
71 nId ( Id ),
72 fnCreatePage( fnPage ),
73 fnGetRanges ( fnRanges ),
74 pTabPage ( 0 ),
75 bOnDemand ( bDemand ),
76 bRefresh ( false )
78 if ( !fnCreatePage )
80 SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
81 if ( pFact )
83 fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
84 fnGetRanges = pFact->GetTabPageRangesFunc( nId );
90 SfxTabDialogItem::SfxTabDialogItem( const SfxTabDialogItem& rAttr, SfxItemPool* pItemPool )
91 : SfxSetItem( rAttr, pItemPool )
95 SfxTabDialogItem::SfxTabDialogItem( sal_uInt16 nId, const SfxItemSet& rItemSet )
96 : SfxSetItem( nId, rItemSet )
100 SfxPoolItem* SfxTabDialogItem::Clone(SfxItemPool* pToPool) const
102 return new SfxTabDialogItem( *this, pToPool );
105 SfxPoolItem* SfxTabDialogItem::Create(SvStream& /*rStream*/, sal_uInt16 /*nVersion*/) const
107 OSL_FAIL( "Use it only in UI!" );
108 return NULL;
111 typedef std::vector<Data_Impl*> SfxTabDlgData_Impl;
113 struct TabDlg_Impl
115 bool bModified : 1,
116 bModal : 1,
117 bHideResetBtn : 1;
118 SfxTabDlgData_Impl aData;
120 TabDlg_Impl( sal_uInt8 nCnt ) :
122 bModified ( false ),
123 bModal ( true ),
124 bHideResetBtn ( false )
126 aData.reserve( nCnt );
128 ~TabDlg_Impl()
134 static Data_Impl* Find( const SfxTabDlgData_Impl& rArr, sal_uInt16 nId, sal_uInt16* pPos = 0)
136 const sal_uInt16 nCount = rArr.size();
138 for ( sal_uInt16 i = 0; i < nCount; ++i )
140 Data_Impl* pObj = rArr[i];
142 if ( pObj->nId == nId )
144 if ( pPos )
145 *pPos = i;
146 return pObj;
149 return 0;
152 void SfxTabPage::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame)
154 if (pImpl)
155 pImpl->mxFrame = xFrame;
158 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxTabPage::GetFrame()
160 if (pImpl)
161 return pImpl->mxFrame;
162 return ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >();
165 SfxTabPage::SfxTabPage(vcl::Window *pParent, const OString& rID, const OUString& rUIXMLDescription, const SfxItemSet *rAttrSet)
166 : TabPage(pParent, rID, rUIXMLDescription)
167 , pSet ( rAttrSet )
168 , bHasExchangeSupport ( false )
169 , pImpl ( new TabPageImpl )
173 SfxTabPage::~SfxTabPage()
175 disposeOnce();
178 void SfxTabPage::dispose()
180 delete pImpl;
181 pImpl = NULL;
182 TabPage::dispose();
185 bool SfxTabPage::FillItemSet( SfxItemSet* rSet )
187 return pImpl->maItemConn.DoFillItemSet( *rSet, GetItemSet() );
190 void SfxTabPage::Reset( const SfxItemSet* rSet )
192 pImpl->maItemConn.DoApplyFlags( *rSet );
193 pImpl->maItemConn.DoReset( *rSet );
196 void SfxTabPage::ActivatePage( const SfxItemSet& )
197 /* [Description]
199 Default implementation of the virtual ActivatePage method. This method is
200 called when a page of dialogue supports the exchange of data between pages.
201 <SfxTabPage::DeactivatePage(SfxItemSet *)>
206 SfxTabPage::sfxpg SfxTabPage::DeactivatePage( SfxItemSet* )
208 /* [Description]
210 Default implementation of the virtual DeactivatePage method. This method is
211 called by Sfx when leaving a page; the application can, through the return
212 value, control whether to leave the page. If the page is displayed through
213 bHasExchangeSupport which supports data exchange between pages, then a
214 pointer to the exchange set is passed as parameter. This takes on data for
215 the exchange, then the set is available as a parameter in
216 <SfxTabPage::ActivatePage(const SfxItemSet &)>.
218 [Return value]
220 LEAVE_PAGE; Allow leaving the page
224 return LEAVE_PAGE;
229 void SfxTabPage::FillUserData()
231 /* [Description]
233 Virtual method is called by the base class in the destructor to save
234 specific information of the TabPage in the ini-file. When overriding a
235 string must be compiled, which is then flushed with the <SetUserData()>.
243 bool SfxTabPage::IsReadOnly() const
245 return false;
250 const SfxPoolItem* SfxTabPage::GetItem( const SfxItemSet& rSet, sal_uInt16 nSlot, bool bDeep )
252 /* [Description]
254 static Method: hereby are the implementations of the TabPage code
255 being simplified.
259 const SfxItemPool* pPool = rSet.GetPool();
260 sal_uInt16 nWh = pPool->GetWhich( nSlot, bDeep );
261 const SfxPoolItem* pItem = 0;
262 rSet.GetItemState( nWh, true, &pItem );
264 if ( !pItem && nWh != nSlot )
265 pItem = &pPool->GetDefaultItem( nWh );
266 return pItem;
271 const SfxPoolItem* SfxTabPage::GetOldItem( const SfxItemSet& rSet,
272 sal_uInt16 nSlot, bool bDeep )
274 /* [Description]
276 This method returns an attribute for comparison of the old value.
280 const SfxItemSet& rOldSet = GetItemSet();
281 sal_uInt16 nWh = GetWhich( nSlot, bDeep );
282 const SfxPoolItem* pItem = 0;
284 if ( pImpl->mbStandard && rOldSet.GetParent() )
285 pItem = GetItem( *rOldSet.GetParent(), nSlot );
286 else if ( rSet.GetParent() &&
287 SfxItemState::DONTCARE == rSet.GetItemState( nWh ) )
288 pItem = GetItem( *rSet.GetParent(), nSlot );
289 else
290 pItem = GetItem( rOldSet, nSlot );
291 return pItem;
294 void SfxTabPage::PageCreated( const SfxAllItemSet& /*aSet*/ )
296 DBG_ASSERT(false, "SfxTabPage::PageCreated should not be called");
301 void SfxTabPage::AddItemConnection( sfx::ItemConnectionBase* pConnection )
303 pImpl->maItemConn.AddConnection( pConnection );
306 SfxTabDialog* SfxTabPage::GetTabDialog() const
308 return dynamic_cast<SfxTabDialog*>(GetParentDialog());
313 SfxTabDialog::SfxTabDialog
315 SfxViewFrame* pViewFrame, // Frame, to which the Dialog belongs
316 vcl::Window* pParent, // Parent Window
317 const OUString& rID, const OUString& rUIXMLDescription, //Dialog Name, Dialog .ui path
318 const SfxItemSet* pItemSet, // Itemset with the data;
319 // can be NULL, when Pages are onDemand
320 bool bEditFmt // when yes -> additional Button for standard
322 : TabDialog(pParent, rID, rUIXMLDescription)
323 , pFrame(pViewFrame)
324 , pSet(pItemSet ? new SfxItemSet(*pItemSet) : 0)
325 , pOutSet(0)
326 , pRanges(0)
327 , nAppPageId(USHRT_MAX)
328 , bItemsReset(false)
329 , bStandardPushed(false)
330 , pExampleSet(0)
332 Init_Impl(bEditFmt);
337 SfxTabDialog::SfxTabDialog
339 /* [Description]
341 Constructor, temporary without Frame
345 vcl::Window* pParent, // Parent Window
346 const OUString& rID, const OUString& rUIXMLDescription, //Dialog Name, Dialog .ui path
347 const SfxItemSet* pItemSet, // Itemset with the data;
348 // can be NULL, when Pages are onDemand
349 bool bEditFmt // when yes -> additional Button for standard
351 : TabDialog(pParent, rID, rUIXMLDescription)
352 , pFrame(0)
353 , pSet(pItemSet ? new SfxItemSet(*pItemSet) : 0)
354 , pOutSet(0)
355 , pRanges(0)
356 , nAppPageId(USHRT_MAX)
357 , bItemsReset(false)
358 , bStandardPushed(false)
359 , pExampleSet(0)
361 Init_Impl(bEditFmt);
362 DBG_WARNING( "Please use the Construtor with the ViewFrame" );
367 SfxTabDialog::~SfxTabDialog()
369 disposeOnce();
372 void SfxTabDialog::dispose()
374 SavePosAndId();
376 for ( SfxTabDlgData_Impl::const_iterator it = pImpl->aData.begin(); it != pImpl->aData.end(); ++it )
378 Data_Impl* pDataObject = *it;
380 if ( pDataObject->pTabPage )
382 // save settings of all pages (user data)
383 pDataObject->pTabPage->FillUserData();
384 OUString aPageData( pDataObject->pTabPage->GetUserData() );
385 if ( !aPageData.isEmpty() )
387 // save settings of all pages (user data)
388 OUString sConfigId = OStringToOUString(pDataObject->pTabPage->GetConfigId(),
389 RTL_TEXTENCODING_UTF8);
390 if (sConfigId.isEmpty())
392 SAL_WARN("sfx.config", "Tabpage needs to be converted to .ui format");
393 sConfigId = OUString::number(pDataObject->nId);
396 SvtViewOptions aPageOpt(E_TABPAGE, sConfigId);
397 aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) );
400 if ( pDataObject->bOnDemand )
401 delete &pDataObject->pTabPage->GetItemSet();
402 pDataObject->pTabPage.disposeAndClear();
404 delete pDataObject;
405 pDataObject = NULL;
408 delete pImpl;
409 pImpl = NULL;
410 delete pSet;
411 pSet = NULL;
412 delete pOutSet;
413 pOutSet = NULL;
414 delete pExampleSet;
415 pExampleSet = NULL;
416 delete [] pRanges;
417 pRanges = NULL;
419 if (m_bOwnsBaseFmtBtn)
420 m_pBaseFmtBtn.disposeAndClear();
421 if (m_bOwnsResetBtn)
422 m_pResetBtn.disposeAndClear();
423 if (m_bOwnsHelpBtn)
424 m_pHelpBtn.disposeAndClear();
425 if (m_bOwnsCancelBtn)
426 m_pCancelBtn.disposeAndClear();
427 if (m_bOwnsOKBtn)
428 m_pOKBtn.disposeAndClear();
429 m_pBox.clear();
430 m_pTabCtrl.clear();
431 m_pOKBtn.clear();
432 m_pApplyBtn.clear();
433 m_pUserBtn.clear();
434 m_pCancelBtn.clear();
435 m_pHelpBtn.clear();
436 m_pResetBtn.clear();
437 m_pBaseFmtBtn.clear();
438 m_pActionArea.clear();
440 TabDialog::dispose();
443 void SfxTabDialog::Init_Impl(bool bFmtFlag)
444 /* [Description]
446 internal initialization of the dialogue
449 m_pBox = get_content_area();
450 assert(m_pBox);
451 m_pUIBuilder->get(m_pTabCtrl, "tabcontrol");
453 pImpl = new TabDlg_Impl(m_pTabCtrl->GetPageCount());
455 m_pActionArea = get_action_area();
456 assert(m_pActionArea);
458 m_pOKBtn = m_pUIBuilder->get<PushButton>("ok");
459 m_bOwnsOKBtn = m_pOKBtn == nullptr;
460 if (m_bOwnsOKBtn)
461 m_pOKBtn = VclPtr<OKButton>::Create(m_pActionArea);
463 m_pApplyBtn = m_pUIBuilder->get<PushButton>("apply");
464 m_pUserBtn = m_pUIBuilder->get<PushButton>("user");
465 m_pCancelBtn = m_pUIBuilder->get<CancelButton>("cancel");
466 m_bOwnsCancelBtn = m_pCancelBtn == nullptr;
467 if (m_bOwnsCancelBtn)
468 m_pCancelBtn = VclPtr<CancelButton>::Create(m_pActionArea);
470 m_pHelpBtn = m_pUIBuilder->get<HelpButton>("help");
471 m_bOwnsHelpBtn = m_pHelpBtn == nullptr;
472 if (m_bOwnsHelpBtn)
473 m_pHelpBtn = VclPtr<HelpButton>::Create(m_pActionArea);
475 m_pResetBtn = m_pUIBuilder->get<PushButton>("reset");
476 m_bOwnsResetBtn = m_pResetBtn == nullptr;
477 if (m_bOwnsResetBtn)
478 m_pResetBtn = VclPtr<PushButton>::Create(m_pActionArea.get());
479 else
480 pImpl->bHideResetBtn = !m_pResetBtn->IsVisible();
482 m_pBaseFmtBtn = m_pUIBuilder->get<PushButton>("standard");
483 m_bOwnsBaseFmtBtn = m_pBaseFmtBtn == nullptr;
484 if (m_bOwnsBaseFmtBtn)
485 m_pBaseFmtBtn = VclPtr<PushButton>::Create(m_pActionArea.get());
487 m_pOKBtn->SetClickHdl( LINK( this, SfxTabDialog, OkHdl ) );
488 m_pCancelBtn->SetClickHdl( LINK( this, SfxTabDialog, CancelHdl ) );
489 m_pResetBtn->SetClickHdl( LINK( this, SfxTabDialog, ResetHdl ) );
490 m_pResetBtn->SetText( SfxResId( STR_RESET ).toString() );
491 m_pTabCtrl->SetActivatePageHdl(
492 LINK( this, SfxTabDialog, ActivatePageHdl ) );
493 m_pTabCtrl->SetDeactivatePageHdl(
494 LINK( this, SfxTabDialog, DeactivatePageHdl ) );
495 m_pActionArea->Show();
496 m_pBox->Show();
497 m_pTabCtrl->Show();
498 m_pOKBtn->Show();
499 m_pCancelBtn->Show();
500 m_pHelpBtn->Show();
501 m_pResetBtn->Show();
502 m_pResetBtn->SetHelpId( HID_TABDLG_RESET_BTN );
504 if ( m_pUserBtn )
506 m_pUserBtn->SetClickHdl( LINK( this, SfxTabDialog, UserHdl ) );
507 m_pUserBtn->Show();
510 if ( bFmtFlag )
512 m_pBaseFmtBtn->SetText( SfxResId( STR_STANDARD_SHORTCUT ).toString() );
513 m_pBaseFmtBtn->SetClickHdl( LINK( this, SfxTabDialog, BaseFmtHdl ) );
514 m_pBaseFmtBtn->SetHelpId( HID_TABDLG_STANDARD_BTN );
515 m_pBaseFmtBtn->Show();
518 if ( pSet )
520 pExampleSet = new SfxItemSet( *pSet );
521 pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
525 void SfxTabDialog::RemoveResetButton()
527 m_pResetBtn->Hide();
528 pImpl->bHideResetBtn = true;
531 void SfxTabDialog::RemoveStandardButton()
533 m_pBaseFmtBtn->Hide();
536 short SfxTabDialog::Execute()
538 if ( !m_pTabCtrl->GetPageCount() )
539 return RET_CANCEL;
540 Start_Impl();
541 return TabDialog::Execute();
546 void SfxTabDialog::StartExecuteModal( const Link<>& rEndDialogHdl )
548 if ( !m_pTabCtrl->GetPageCount() )
549 return;
550 Start_Impl();
551 TabDialog::StartExecuteModal( rEndDialogHdl );
556 void SfxTabDialog::Start( bool bShow )
558 pImpl->bModal = false;
559 Start_Impl();
561 if ( bShow )
562 Show();
564 if ( IsVisible() && ( !HasChildPathFocus() || HasFocus() ) )
565 GrabFocusToFirstControl();
570 void SfxTabDialog::SetApplyHandler(const Link<>& _rHdl)
572 DBG_ASSERT( m_pApplyBtn, "SfxTabDialog::GetApplyHandler: no apply button enabled!" );
573 if ( m_pApplyBtn )
574 m_pApplyBtn->SetClickHdl( _rHdl );
579 void SfxTabDialog::Start_Impl()
581 assert(pImpl->aData.size() == m_pTabCtrl->GetPageCount()
582 && "not all pages registered");
583 sal_uInt16 nActPage = m_pTabCtrl->GetPageId( 0 );
585 // load old settings, when exists
586 SvtViewOptions aDlgOpt(E_TABDIALOG, OStringToOUString(GetHelpId(),RTL_TEXTENCODING_UTF8));
587 if ( aDlgOpt.Exists() )
589 SetWindowState(OUStringToOString(aDlgOpt.GetWindowState().getStr(), RTL_TEXTENCODING_ASCII_US));
591 // initial TabPage from Program/Help/config
592 nActPage = (sal_uInt16)aDlgOpt.GetPageID();
594 if ( USHRT_MAX != nAppPageId )
595 nActPage = nAppPageId;
596 else
598 sal_uInt16 nAutoTabPageId = SfxGetpApp()->Get_Impl()->nAutoTabPageId;
599 if ( nAutoTabPageId )
600 nActPage = nAutoTabPageId;
603 if ( TAB_PAGE_NOTFOUND == m_pTabCtrl->GetPagePos( nActPage ) )
604 nActPage = m_pTabCtrl->GetPageId( 0 );
606 else if ( USHRT_MAX != nAppPageId && TAB_PAGE_NOTFOUND != m_pTabCtrl->GetPagePos( nAppPageId ) )
607 nActPage = nAppPageId;
609 m_pTabCtrl->SetCurPageId( nActPage );
610 ActivatePageHdl( m_pTabCtrl );
613 void SfxTabDialog::AddTabPage( sal_uInt16 nId, const OUString &rRiderText, bool bItemsOnDemand, sal_uInt16 nPos )
615 AddTabPage( nId, rRiderText, 0, 0, bItemsOnDemand, nPos );
619 Adds a page to the dialog. The Name must correspond to a entry in the
620 TabControl in the dialog .ui
622 sal_uInt16 SfxTabDialog::AddTabPage
624 const OString &rName, // Page ID
625 CreateTabPage pCreateFunc, // Pointer to the Factory Method
626 GetTabPageRanges pRangesFunc, // Pointer to the Method for quering
627 // Ranges onDemand
628 bool bItemsOnDemand // indicates whether the set of this page is
629 // requested when created
632 sal_uInt16 nId = m_pTabCtrl->GetPageId(rName);
633 pImpl->aData.push_back(
634 new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
635 return nId;
639 Adds a page to the dialog. The Name must correspond to a entry in the
640 TabControl in the dialog .ui
642 sal_uInt16 SfxTabDialog::AddTabPage
644 const OString &rName, // Page ID
645 sal_uInt16 nPageCreateId // Identifier of the Factory Method to create the page
648 SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
649 assert(pFact);
650 CreateTabPage pCreateFunc = pFact->GetTabPageCreatorFunc(nPageCreateId);
651 assert(pCreateFunc);
652 GetTabPageRanges pRangesFunc = pFact->GetTabPageRangesFunc(nPageCreateId);
653 sal_uInt16 nPageId = m_pTabCtrl->GetPageId(rName);
654 pImpl->aData.push_back(new Data_Impl(nPageId, pCreateFunc, pRangesFunc, false));
655 return nPageId;
660 void SfxTabDialog::AddTabPage
662 /* [Description]
664 Add a page to the dialog. The Rider text is passed on, the page has no
665 counterpart in the TabControl in the resource of the dialogue.
669 sal_uInt16 nId,
670 const OUString& rRiderText,
671 CreateTabPage pCreateFunc,
672 GetTabPageRanges pRangesFunc,
673 bool bItemsOnDemand,
674 sal_uInt16 nPos
677 DBG_ASSERT( TAB_PAGE_NOTFOUND == m_pTabCtrl->GetPagePos( nId ),
678 "Double Page-Ids in the Tabpage" );
679 m_pTabCtrl->InsertPage( nId, rRiderText, nPos );
680 pImpl->aData.push_back(
681 new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
684 void SfxTabDialog::RemoveTabPage( sal_uInt16 nId )
686 /* [Description]
688 Delete the TabPage with ID nId
692 sal_uInt16 nPos = 0;
693 m_pTabCtrl->RemovePage( nId );
694 Data_Impl* pDataObject = Find( pImpl->aData, nId, &nPos );
696 if ( pDataObject )
698 if ( pDataObject->pTabPage )
700 pDataObject->pTabPage->FillUserData();
701 OUString aPageData( pDataObject->pTabPage->GetUserData() );
702 if ( !aPageData.isEmpty() )
704 // save settings of this page (user data)
705 OUString sConfigId = OStringToOUString(pDataObject->pTabPage->GetConfigId(),
706 RTL_TEXTENCODING_UTF8);
707 if (sConfigId.isEmpty())
709 SAL_WARN("sfx.config", "Tabpage needs to be converted to .ui format");
710 sConfigId = OUString::number(pDataObject->nId);
713 SvtViewOptions aPageOpt(E_TABPAGE, sConfigId);
714 aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) );
717 if ( pDataObject->bOnDemand )
718 delete &pDataObject->pTabPage->GetItemSet();
719 pDataObject->pTabPage.disposeAndClear();
722 delete pDataObject;
723 pImpl->aData.erase( pImpl->aData.begin() + nPos );
725 else
727 SAL_INFO( "sfx.dialog", "TabPage-Id not known" );
731 void SfxTabDialog::RemoveTabPage(const OString &rName)
733 RemoveTabPage(m_pTabCtrl->GetPageId(rName));
738 void SfxTabDialog::PageCreated
740 /* [Description]
742 Default implementation of the virtual method. This is called immediately
743 after creating a page. Here the dialogue can call the TabPage Method
744 directly.
748 sal_uInt16, // Id of the created page
749 SfxTabPage& // Reference to the created page
756 SfxItemSet* SfxTabDialog::GetInputSetImpl()
758 /* [Description]
760 Derived classes may create new storage for the InputSet. This has to be
761 released in the Destructor. To do this, this method must be called.
765 return pSet;
770 SfxTabPage* SfxTabDialog::GetTabPage( sal_uInt16 nPageId ) const
772 /* [Description]
774 Return TabPage with the specified Id.
778 sal_uInt16 nPos = 0;
779 Data_Impl* pDataObject = Find( pImpl->aData, nPageId, &nPos );
781 if ( pDataObject )
782 return pDataObject->pTabPage;
783 return NULL;
786 void SfxTabDialog::SavePosAndId()
788 // save settings (screen position and current page)
789 SvtViewOptions aDlgOpt(E_TABDIALOG, OStringToOUString(GetHelpId(),RTL_TEXTENCODING_UTF8));
790 aDlgOpt.SetWindowState(OStringToOUString(GetWindowState(WINDOWSTATE_MASK_POS),RTL_TEXTENCODING_ASCII_US));
791 // to-do replace with name of page when all pages are converted to .ui
792 aDlgOpt.SetPageID( m_pTabCtrl->GetCurPageId() );
797 short SfxTabDialog::Ok()
799 /* [Description]
801 Ok handler for the Dialogue.
803 Dialog's current location and current page are saved for the next time
804 the dialog is shown.
806 The OutputSet is created and for each page this or the special OutputSet
807 is set by calling the method <SfxTabPage::FillItemSet(SfxItemSet &)>, to
808 insert the entered data by the user into the set.
810 [Return value]
812 RET_OK: if at least one page has returned from FillItemSet,
813 otherwise RET_CANCEL.
816 SavePosAndId(); //See fdo#38828 "Apply" resetting window position
818 if ( !pOutSet )
820 if ( !pExampleSet && pSet )
821 pOutSet = pSet->Clone( false ); // without Items
822 else if ( pExampleSet )
823 pOutSet = new SfxItemSet( *pExampleSet );
825 bool bModified = false;
827 for ( SfxTabDlgData_Impl::const_iterator it = pImpl->aData.begin(); it != pImpl->aData.end(); ++it )
829 Data_Impl* pDataObject = *it;
830 SfxTabPage* pTabPage = pDataObject->pTabPage;
832 if ( pTabPage )
834 if ( pDataObject->bOnDemand )
836 SfxItemSet& rSet = (SfxItemSet&)pTabPage->GetItemSet();
837 rSet.ClearItem();
838 bModified |= pTabPage->FillItemSet( &rSet );
840 else if ( pSet && !pTabPage->HasExchangeSupport() )
842 SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
844 if ( pTabPage->FillItemSet( &aTmp ) )
846 bModified |= true;
847 if (pExampleSet)
848 pExampleSet->Put( aTmp );
849 pOutSet->Put( aTmp );
855 if ( pImpl->bModified || ( pOutSet && pOutSet->Count() > 0 ) )
856 bModified |= true;
858 if (bStandardPushed)
859 bModified |= true;
860 return bModified ? RET_OK : RET_CANCEL;
863 IMPL_LINK_NOARG(SfxTabDialog, CancelHdl)
865 EndDialog( RET_USER_CANCEL );
866 return 0;
871 SfxItemSet* SfxTabDialog::CreateInputItemSet( sal_uInt16 )
873 /* [Description]
875 Default implementation of the virtual Method.
876 This is called when pages create their sets onDemand.
880 SAL_WARN( "sfx.dialog", "CreateInputItemSet not implemented" );
881 return new SfxAllItemSet( SfxGetpApp()->GetPool() );
886 void SfxTabDialog::RefreshInputSet()
888 /* [Description]
890 Default implementation of the virtual Method.
891 This is called, when <SfxTabPage::DeactivatePage(SfxItemSet *)>
892 returns <SfxTabPage::REFRESH_SET>.
896 SAL_INFO ( "sfx.dialog", "RefreshInputSet not implemented" );
901 IMPL_LINK_NOARG(SfxTabDialog, OkHdl)
903 /* [Description]
905 Handler of the Ok-Buttons
906 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
907 Returns <SfxTabPage::LEAVE_PAGE>, <SfxTabDialog::Ok()> is called
908 and the Dialog is ended.
912 if (PrepareLeaveCurrentPage())
914 if ( pImpl->bModal )
915 EndDialog( Ok() );
916 else
918 Ok();
919 Close();
922 return 0;
925 bool SfxTabDialog::Apply()
927 bool bApplied = false;
928 if (PrepareLeaveCurrentPage())
929 bApplied = (Ok() == RET_OK);
930 return bApplied;
935 bool SfxTabDialog::PrepareLeaveCurrentPage()
937 sal_uInt16 const nId = m_pTabCtrl->GetCurPageId();
938 SfxTabPage* pPage = dynamic_cast<SfxTabPage*> (m_pTabCtrl->GetTabPage( nId ));
939 bool bEnd = !pPage;
941 if ( pPage )
943 int nRet = SfxTabPage::LEAVE_PAGE;
944 if ( pSet )
946 SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
948 if ( pPage->HasExchangeSupport() )
949 nRet = pPage->DeactivatePage( &aTmp );
950 else
951 nRet = pPage->DeactivatePage( NULL );
953 if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE
954 && aTmp.Count() )
956 pExampleSet->Put( aTmp );
957 pOutSet->Put( aTmp );
960 else
961 nRet = pPage->DeactivatePage( NULL );
962 bEnd = nRet;
965 return bEnd;
971 IMPL_LINK_NOARG(SfxTabDialog, UserHdl)
973 /* [Description]
975 Handler of the User-Buttons
976 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
977 returns this <SfxTabPage::LEAVE_PAGE> and <SfxTabDialog::Ok()> is called.
978 Then the Dialog is ended with the Return value <SfxTabDialog::Ok()>
982 if ( PrepareLeaveCurrentPage () )
984 short nRet = Ok();
986 if ( RET_OK == nRet )
987 nRet = RET_USER;
988 else
989 nRet = RET_USER_CANCEL;
990 EndDialog( nRet );
992 return 0;
997 IMPL_LINK_NOARG(SfxTabDialog, ResetHdl)
999 /* [Description]
1001 Handler behind the reset button.
1002 The Current Page is new initialized with their initial data, all the
1003 settings that the user has made on this page are repealed.
1007 const sal_uInt16 nId = m_pTabCtrl->GetCurPageId();
1008 Data_Impl* pDataObject = Find( pImpl->aData, nId );
1009 DBG_ASSERT( pDataObject, "Id not known" );
1011 if ( pDataObject->bOnDemand )
1013 // CSet on AIS has problems here, thus separated
1014 const SfxItemSet* pItemSet = &pDataObject->pTabPage->GetItemSet();
1015 pDataObject->pTabPage->Reset( pItemSet );
1017 else
1018 pDataObject->pTabPage->Reset( pSet );
1019 return 0;
1024 IMPL_LINK_NOARG(SfxTabDialog, BaseFmtHdl)
1026 /* [Description]
1028 Handler behind the Standard-Button.
1029 This button is available when editing style sheets. All the set attributes
1030 in the edited stylesheet are deleted.
1034 bStandardPushed = true;
1036 const sal_uInt16 nId = m_pTabCtrl->GetCurPageId();
1037 Data_Impl* pDataObject = Find( pImpl->aData, nId );
1038 DBG_ASSERT( pDataObject, "Id not known" );
1040 if ( pDataObject->fnGetRanges )
1042 if ( !pExampleSet )
1043 pExampleSet = new SfxItemSet( *pSet );
1045 const SfxItemPool* pPool = pSet->GetPool();
1046 const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)();
1047 SfxItemSet aTmpSet( *pExampleSet );
1049 while ( *pTmpRanges )
1051 const sal_uInt16* pU = pTmpRanges + 1;
1053 if ( *pTmpRanges == *pU )
1055 // Range which two identical values -> only set one Item
1056 sal_uInt16 nWh = pPool->GetWhich( *pTmpRanges );
1057 pExampleSet->ClearItem( nWh );
1058 aTmpSet.ClearItem( nWh );
1059 // At the Outset of InvalidateItem,
1060 // so that the change takes effect
1061 pOutSet->InvalidateItem( nWh );
1063 else
1065 // Correct Range with multiple values
1066 sal_uInt16 nTmp = *pTmpRanges, nTmpEnd = *pU;
1067 DBG_ASSERT( nTmp <= nTmpEnd, "Range is sorted the wrong way" );
1069 if ( nTmp > nTmpEnd )
1071 // If really sorted wrongly, then set new
1072 sal_uInt16 nTmp1 = nTmp;
1073 nTmp = nTmpEnd;
1074 nTmpEnd = nTmp1;
1077 while ( nTmp <= nTmpEnd )
1079 // Iterate over the Range and set the Items
1080 sal_uInt16 nWh = pPool->GetWhich( nTmp );
1081 pExampleSet->ClearItem( nWh );
1082 aTmpSet.ClearItem( nWh );
1083 // At the Outset of InvalidateItem,
1084 // so that the change takes effect
1085 pOutSet->InvalidateItem( nWh );
1086 nTmp++;
1089 // Go to the next pair
1090 pTmpRanges += 2;
1092 // Set all Items as new -> the call the current Page Reset()
1093 DBG_ASSERT( pDataObject->pTabPage, "the Page is gone" );
1094 pDataObject->pTabPage->Reset( &aTmpSet );
1095 pDataObject->pTabPage->pImpl->mbStandard = true;
1097 return 1;
1102 IMPL_LINK( SfxTabDialog, ActivatePageHdl, TabControl *, pTabCtrl )
1104 /* [Description]
1106 Handler that is called by StarView for switching to a different page.
1107 If the page not exist yet then it is created and the virtual Method
1108 <SfxTabDialog::PageCreated( sal_uInt16, SfxTabPage &)> is called. If the page
1109 exist, then the if possible the <SfxTabPage::Reset(const SfxItemSet &)> or
1110 <SfxTabPage::ActivatePage(const SfxItemSet &)> is called.
1114 sal_uInt16 nId = pTabCtrl->GetCurPageId();
1116 DBG_ASSERT( pImpl->aData.size(), "no Pages registered" );
1117 SfxGetpApp();
1119 // Tab Page schon da?
1120 VclPtr<SfxTabPage> pTabPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId ));
1121 Data_Impl* pDataObject = Find( pImpl->aData, nId );
1123 //UUUU fallback to 1st page when requested one does not exist
1124 if(!pDataObject && pTabCtrl->GetPageCount())
1126 pTabCtrl->SetCurPageId(pTabCtrl->GetPageId(0));
1127 nId = pTabCtrl->GetCurPageId();
1128 pTabPage = dynamic_cast< SfxTabPage* >(pTabCtrl->GetTabPage(nId));
1129 pDataObject = Find(pImpl->aData, nId);
1132 if (!pDataObject)
1134 SAL_WARN("sfx.config", "Tab Page ID not known, this is pretty serious and needs investigation");
1135 return 0;
1138 // Create TabPage if possible:
1139 if ( !pTabPage )
1141 const SfxItemSet* pTmpSet = 0;
1143 if ( pSet )
1145 if ( bItemsReset && pSet->GetParent() )
1146 pTmpSet = pSet->GetParent();
1147 else
1148 pTmpSet = pSet;
1151 if ( pTmpSet && !pDataObject->bOnDemand )
1152 pTabPage = (pDataObject->fnCreatePage)( pTabCtrl, pTmpSet );
1153 else
1154 pTabPage = (pDataObject->fnCreatePage)
1155 ( pTabCtrl, CreateInputItemSet( nId ) );
1156 DBG_ASSERT( nullptr == pDataObject->pTabPage, "create TabPage more than once" );
1157 pDataObject->pTabPage = pTabPage;
1159 OUString sConfigId = OStringToOUString(pTabPage->GetConfigId(), RTL_TEXTENCODING_UTF8);
1160 if (sConfigId.isEmpty())
1162 SAL_WARN("sfx.config", "Tabpage needs to be converted to .ui format");
1163 sConfigId = OUString::number(pDataObject->nId);
1165 SvtViewOptions aPageOpt(E_TABPAGE, sConfigId);
1166 OUString sUserData;
1167 Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME );
1168 OUString aTemp;
1169 if ( aUserItem >>= aTemp )
1170 sUserData = aTemp;
1171 pTabPage->SetUserData( sUserData );
1172 Size aSiz = pTabPage->GetSizePixel();
1174 Size aCtrlSiz = pTabCtrl->GetTabPageSizePixel();
1175 // Only set Size on TabControl when < as TabPage
1176 if ( aCtrlSiz.Width() < aSiz.Width() ||
1177 aCtrlSiz.Height() < aSiz.Height() )
1179 pTabCtrl->SetTabPageSizePixel( aSiz );
1182 PageCreated( nId, *pTabPage );
1184 if ( pDataObject->bOnDemand )
1185 pTabPage->Reset( &pTabPage->GetItemSet() );
1186 else
1187 pTabPage->Reset( pSet );
1189 pTabCtrl->SetTabPage( nId, pTabPage );
1191 else if ( pDataObject->bRefresh )
1192 pTabPage->Reset( pSet );
1193 pDataObject->bRefresh = false;
1195 if ( pExampleSet )
1196 pTabPage->ActivatePage( *pExampleSet );
1197 bool bReadOnly = pTabPage->IsReadOnly();
1198 ( bReadOnly || pImpl->bHideResetBtn ) ? m_pResetBtn->Hide() : m_pResetBtn->Show();
1199 return 0;
1204 IMPL_LINK_TYPED( SfxTabDialog, DeactivatePageHdl, TabControl *, pTabCtrl, bool )
1206 /* [Description]
1208 Handler that is called by StarView before leaving a page.
1210 [Cross-reference]
1212 <SfxTabPage::DeactivatePage(SfxItemSet *)>
1216 sal_uInt16 nId = pTabCtrl->GetCurPageId();
1217 SfxGetpApp();
1218 SfxTabPage *pPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId ));
1219 DBG_ASSERT( pPage, "no active Page" );
1220 if (!pPage)
1221 return false;
1222 #ifdef DBG_UTIL
1223 Data_Impl* pDataObject = Find( pImpl->aData, pTabCtrl->GetCurPageId() );
1224 DBG_ASSERT( pDataObject, "no Data structure for current page" );
1225 if ( pPage->HasExchangeSupport() && pDataObject->bOnDemand )
1227 DBG_WARNING( "Data exchange in ItemsOnDemand is not desired!" );
1229 #endif
1231 int nRet = SfxTabPage::LEAVE_PAGE;
1233 if ( !pExampleSet && pPage->HasExchangeSupport() && pSet )
1234 pExampleSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
1236 if ( pSet )
1238 SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1240 if ( pPage->HasExchangeSupport() )
1241 nRet = pPage->DeactivatePage( &aTmp );
1242 else
1243 nRet = pPage->DeactivatePage( NULL );
1244 if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE &&
1245 aTmp.Count() )
1247 pExampleSet->Put( aTmp );
1248 pOutSet->Put( aTmp );
1251 else
1253 if ( pPage->HasExchangeSupport() ) //!!!
1255 if ( !pExampleSet )
1257 SfxItemPool* pPool = pPage->GetItemSet().GetPool();
1258 pExampleSet =
1259 new SfxItemSet( *pPool, GetInputRanges( *pPool ) );
1261 nRet = pPage->DeactivatePage( pExampleSet );
1263 else
1264 nRet = pPage->DeactivatePage( NULL );
1267 if ( nRet & SfxTabPage::REFRESH_SET )
1269 RefreshInputSet();
1270 // Flag all Pages as to be initialized as new
1272 for ( SfxTabDlgData_Impl::const_iterator it = pImpl->aData.begin(); it != pImpl->aData.end(); ++it )
1274 Data_Impl* pObj = *it;
1276 if ( pObj->pTabPage.get() != pPage ) // Do not refresh own Page anymore
1277 pObj->bRefresh = true;
1278 else
1279 pObj->bRefresh = false;
1282 if ( nRet & SfxTabPage::LEAVE_PAGE )
1283 return true;
1284 else
1285 return false;
1290 void SfxTabDialog::ShowPage( sal_uInt16 nId )
1292 /* [Description]
1294 The TabPage is activated with the specified Id.
1298 m_pTabCtrl->SetCurPageId( nId );
1299 ActivatePageHdl( m_pTabCtrl );
1304 const sal_uInt16* SfxTabDialog::GetInputRanges( const SfxItemPool& rPool )
1306 /* [Description]
1308 Makes the set over the range of all pages of the dialogue. Pages have the
1309 static method for querying their range in AddTabPage, ie deliver their
1310 sets onDemand.
1312 [Return value]
1314 Pointer to a null-terminated array of sal_uInt16. This array belongs to the
1315 dialog and is deleted when the dialogue is destroy.
1317 [Cross-reference]
1319 <SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, bool)>
1320 <SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)>
1321 <SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)>
1325 if ( pSet )
1327 SAL_WARN( "sfx.dialog", "Set already exists!" );
1328 return pSet->GetRanges();
1331 if ( pRanges )
1332 return pRanges;
1333 std::vector<sal_uInt16> aUS;
1335 for ( SfxTabDlgData_Impl::const_iterator it = pImpl->aData.begin(); it != pImpl->aData.end(); ++it )
1337 Data_Impl* pDataObject = *it;
1339 if ( pDataObject->fnGetRanges )
1341 const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)();
1342 const sal_uInt16* pIter = pTmpRanges;
1344 sal_uInt16 nLen;
1345 for( nLen = 0; *pIter; ++nLen, ++pIter )
1347 aUS.insert( aUS.end(), pTmpRanges, pTmpRanges + nLen );
1351 //! Remove duplicated Ids?
1353 sal_uInt16 nCount = aUS.size();
1354 for ( sal_uInt16 i = 0; i < nCount; ++i )
1355 aUS[i] = rPool.GetWhich( aUS[i] );
1358 // sort
1359 if ( aUS.size() > 1 )
1361 std::sort( aUS.begin(), aUS.end() );
1364 pRanges = new sal_uInt16[aUS.size() + 1];
1365 std::copy( aUS.begin(), aUS.end(), pRanges );
1366 pRanges[aUS.size()] = 0;
1367 return pRanges;
1372 void SfxTabDialog::SetInputSet( const SfxItemSet* pInSet )
1374 /* [Description]
1376 With this method the Input-Set can subsequently be set initially or re-set.
1380 bool bSet = ( pSet != NULL );
1381 delete pSet;
1382 pSet = pInSet ? new SfxItemSet(*pInSet) : 0;
1384 if (!bSet && !pExampleSet && !pOutSet && pSet)
1386 pExampleSet = new SfxItemSet( *pSet );
1387 pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
1391 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */