Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / dialog / tabdlg.cxx
blobfe4e8be65a8c7c3aab0815d0083b18c641ad7bac
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <limits.h>
31 #include <stdlib.h>
32 #include <algorithm>
33 #include <vcl/msgbox.hxx>
34 #include <unotools/viewoptions.hxx>
36 #include "appdata.hxx"
37 #include "sfxtypes.hxx"
38 #include <sfx2/minarray.hxx>
39 #include <sfx2/tabdlg.hxx>
40 #include <sfx2/viewfrm.hxx>
41 #include <sfx2/app.hxx>
42 #include "sfx2/sfxresid.hxx"
43 #include "sfx2/sfxhelp.hxx"
44 #include <sfx2/ctrlitem.hxx>
45 #include <sfx2/bindings.hxx>
46 #include <sfx2/sfxdlg.hxx>
47 #include <sfx2/itemconnect.hxx>
49 #include "dialog.hrc"
50 #include "helpid.hrc"
52 using namespace ::com::sun::star::uno;
53 using namespace ::rtl;
55 #define USERITEM_NAME OUString("UserItem")
57 TYPEINIT1(SfxTabDialogItem,SfxSetItem);
59 struct TabPageImpl
61 sal_Bool mbStandard;
62 sfx::ItemConnectionArray maItemConn;
63 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;
65 TabPageImpl() : mbStandard( sal_False ) {}
68 struct Data_Impl
70 sal_uInt16 nId; // The ID
71 CreateTabPage fnCreatePage; // Pointer to Factory
72 GetTabPageRanges fnGetRanges; // Pointer to Ranges-Function
73 SfxTabPage* pTabPage; // The TabPage itself
74 sal_Bool bOnDemand; // Flag: ItemSet onDemand
75 sal_Bool bRefresh; // Flag: Page must be re-initialized
77 // Constructor
78 Data_Impl( sal_uInt16 Id, CreateTabPage fnPage,
79 GetTabPageRanges fnRanges, sal_Bool bDemand ) :
81 nId ( Id ),
82 fnCreatePage( fnPage ),
83 fnGetRanges ( fnRanges ),
84 pTabPage ( 0 ),
85 bOnDemand ( bDemand ),
86 bRefresh ( sal_False )
88 if ( !fnCreatePage )
90 SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
91 if ( pFact )
93 fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
94 fnGetRanges = pFact->GetTabPageRangesFunc( nId );
100 SfxTabDialogItem::SfxTabDialogItem( const SfxTabDialogItem& rAttr, SfxItemPool* pItemPool )
101 : SfxSetItem( rAttr, pItemPool )
105 SfxTabDialogItem::SfxTabDialogItem( sal_uInt16 nId, const SfxItemSet& rItemSet )
106 : SfxSetItem( nId, rItemSet )
110 SfxPoolItem* SfxTabDialogItem::Clone(SfxItemPool* pToPool) const
112 return new SfxTabDialogItem( *this, pToPool );
115 SfxPoolItem* SfxTabDialogItem::Create(SvStream& /*rStream*/, sal_uInt16 /*nVersion*/) const
117 OSL_FAIL( "Use it only in UI!" );
118 return NULL;
121 class SfxTabDialogController : public SfxControllerItem
123 SfxTabDialog* pDialog;
124 const SfxItemSet* pSet;
125 public:
126 SfxTabDialogController( sal_uInt16 nSlotId, SfxBindings& rBindings, SfxTabDialog* pDlg )
127 : SfxControllerItem( nSlotId, rBindings )
128 , pDialog( pDlg )
129 , pSet( NULL )
132 ~SfxTabDialogController();
134 virtual void StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState );
137 SfxTabDialogController::~SfxTabDialogController()
139 delete pSet;
142 void SfxTabDialogController::StateChanged( sal_uInt16 /*nSID*/, SfxItemState /*eState*/, const SfxPoolItem* pState )
144 const SfxSetItem* pSetItem = PTR_CAST( SfxSetItem, pState );
145 if ( pSetItem )
147 pSet = pDialog->pSet = pSetItem->GetItemSet().Clone();
148 sal_Bool bDialogStarted = sal_False;
149 for ( sal_uInt16 n=0; n<pDialog->aTabCtrl.GetPageCount(); n++ )
151 sal_uInt16 nPageId = pDialog->aTabCtrl.GetPageId( n );
152 SfxTabPage* pTabPage = dynamic_cast<SfxTabPage*> (pDialog->aTabCtrl.GetTabPage( nPageId ));
153 if ( pTabPage )
155 pTabPage->Reset( pSetItem->GetItemSet() );
156 bDialogStarted = sal_True;
160 if ( bDialogStarted )
161 pDialog->Show();
163 else
164 pDialog->Hide();
167 DECL_PTRARRAY(SfxTabDlgData_Impl, Data_Impl *, 4,4)
169 struct TabDlg_Impl
171 sal_Bool bModified : 1,
172 bModal : 1,
173 bInOK : 1,
174 bHideResetBtn : 1;
175 SfxTabDlgData_Impl* pData;
177 PushButton* pApplyButton;
178 SfxTabDialogController* pController;
180 TabDlg_Impl( sal_uInt8 nCnt ) :
182 bModified ( sal_False ),
183 bModal ( sal_True ),
184 bInOK ( sal_False ),
185 bHideResetBtn ( sal_False ),
186 pData ( new SfxTabDlgData_Impl( nCnt ) ),
187 pApplyButton ( NULL ),
188 pController ( NULL )
192 Data_Impl* Find( SfxTabDlgData_Impl& rArr, sal_uInt16 nId, sal_uInt16* pPos = 0 );
194 Data_Impl* Find( SfxTabDlgData_Impl& rArr, sal_uInt16 nId, sal_uInt16* pPos )
196 const sal_uInt16 nCount = rArr.Count();
198 for ( sal_uInt16 i = 0; i < nCount; ++i )
200 Data_Impl* pObj = rArr[i];
202 if ( pObj->nId == nId )
204 if ( pPos )
205 *pPos = i;
206 return pObj;
209 return 0;
212 void SfxTabPage::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame)
214 if (pImpl)
215 pImpl->mxFrame = xFrame;
218 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxTabPage::GetFrame()
220 if (pImpl)
221 return pImpl->mxFrame;
222 return ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >();
225 SfxTabPage::SfxTabPage( Window *pParent,
226 const ResId &rResId, const SfxItemSet &rAttrSet ) :
228 /* [Description]
230 Constructor
233 TabPage( pParent, rResId ),
235 pSet ( &rAttrSet ),
236 bHasExchangeSupport ( sal_False ),
237 pTabDlg ( NULL ),
238 pImpl ( new TabPageImpl )
242 // -----------------------------------------------------------------------
243 SfxTabPage:: SfxTabPage( Window *pParent, WinBits nStyle, const SfxItemSet &rAttrSet ) :
244 TabPage(pParent, nStyle),
245 pSet ( &rAttrSet ),
246 bHasExchangeSupport ( sal_False ),
247 pTabDlg ( NULL ),
248 pImpl ( new TabPageImpl )
251 // -----------------------------------------------------------------------
253 SfxTabPage::~SfxTabPage()
255 /* [Description]
257 Destructor
261 delete pImpl;
264 // -----------------------------------------------------------------------
266 sal_Bool SfxTabPage::FillItemSet( SfxItemSet& rSet )
268 return pImpl->maItemConn.DoFillItemSet( rSet, GetItemSet() );
271 // -----------------------------------------------------------------------
273 void SfxTabPage::Reset( const SfxItemSet& rSet )
275 pImpl->maItemConn.DoApplyFlags( rSet );
276 pImpl->maItemConn.DoReset( rSet );
279 // -----------------------------------------------------------------------
281 void SfxTabPage::ActivatePage( const SfxItemSet& )
283 /* [Description]
285 Default implementation of the virtual ActivatePage method. This method is
286 called when a page of dialogue supports the exchange of data between pages.
287 <SfxTabPage::DeactivatePage(SfxItemSet *)>
293 // -----------------------------------------------------------------------
295 int SfxTabPage::DeactivatePage( SfxItemSet* )
297 /* [Description]
299 Default implementation of the virtual DeactivatePage method. This method is
300 called by Sfx when leaving a page; the application can, through the return
301 value, control whether to leave the page. If the page is displayed through
302 bHasExchangeSupport which supports data exchange between pages, then a
303 pointer to the exchange set is passed as parameter. This takes on data for
304 the exchange, then the set is available as a parameter in
305 <SfxTabPage::ActivatePage(const SfxItemSet &)>.
307 [Return value]
309 LEAVE_PAGE; Allow leaving the page
313 return LEAVE_PAGE;
316 // -----------------------------------------------------------------------
318 void SfxTabPage::FillUserData()
320 /* [Description]
322 Virtual method is called by the base class in the destructor to save
323 specific information of the TabPage in the ini-file. When overloading a
324 string must be compiled, which is then flushed with the <SetUserData()>.
330 // -----------------------------------------------------------------------
332 sal_Bool SfxTabPage::IsReadOnly() const
334 return sal_False;
337 // -----------------------------------------------------------------------
339 const SfxPoolItem* SfxTabPage::GetItem( const SfxItemSet& rSet, sal_uInt16 nSlot, sal_Bool bDeep )
341 /* [Description]
343 static Method: hereby are the implementations of the TabPage code
344 beeing simplified.
348 const SfxItemPool* pPool = rSet.GetPool();
349 sal_uInt16 nWh = pPool->GetWhich( nSlot, bDeep );
350 const SfxPoolItem* pItem = 0;
351 rSet.GetItemState( nWh, sal_True, &pItem );
353 if ( !pItem && nWh != nSlot )
354 pItem = &pPool->GetDefaultItem( nWh );
355 return pItem;
358 // -----------------------------------------------------------------------
360 const SfxPoolItem* SfxTabPage::GetOldItem( const SfxItemSet& rSet,
361 sal_uInt16 nSlot, sal_Bool bDeep )
363 /* [Description]
365 This method returns an attribute for comparison of the old value.
369 const SfxItemSet& rOldSet = GetItemSet();
370 sal_uInt16 nWh = GetWhich( nSlot, bDeep );
371 const SfxPoolItem* pItem = 0;
373 if ( pImpl->mbStandard && rOldSet.GetParent() )
374 pItem = GetItem( *rOldSet.GetParent(), nSlot );
375 else if ( rSet.GetParent() &&
376 SFX_ITEM_DONTCARE == rSet.GetItemState( nWh ) )
377 pItem = GetItem( *rSet.GetParent(), nSlot );
378 else
379 pItem = GetItem( rOldSet, nSlot );
380 return pItem;
383 void SfxTabPage::PageCreated( SfxAllItemSet /*aSet*/ )
385 DBG_ASSERT(0, "SfxTabPage::PageCreated should not be called");
388 // -----------------------------------------------------------------------
390 void SfxTabPage::AddItemConnection( sfx::ItemConnectionBase* pConnection )
392 pImpl->maItemConn.AddConnection( pConnection );
395 #define INI_LIST(ItemSetPtr) \
396 aTabCtrl ( this, ResId(ID_TABCONTROL,*rResId.GetResMgr() ) ),\
397 aOKBtn ( this ),\
398 pUserBtn ( pUserButtonText? new PushButton(this): 0 ),\
399 aCancelBtn ( this ),\
400 aHelpBtn ( this ),\
401 aResetBtn ( this ),\
402 aBaseFmtBtn ( this ),\
403 pSet ( ItemSetPtr ),\
404 pOutSet ( 0 ),\
405 pImpl ( new TabDlg_Impl( (sal_uInt8)aTabCtrl.GetPageCount() ) ), \
406 pRanges ( 0 ), \
407 nResId ( rResId.GetId() ), \
408 nAppPageId ( USHRT_MAX ), \
409 bItemsReset ( sal_False ),\
410 bFmt ( bEditFmt ),\
411 pExampleSet ( 0 )
413 // -----------------------------------------------------------------------
415 SfxTabDialog::SfxTabDialog
417 /* [Description]
419 Constructor
423 SfxViewFrame* pViewFrame, // Frame, to which the Dialog belongs
424 Window* pParent, // Parent Window
425 const ResId& rResId, // ResourceId
426 const SfxItemSet* pItemSet, // Itemset with the data;
427 // can be NULL, when Pages are onDemand
428 sal_Bool bEditFmt, // Flag: templates are processed
429 // when yes -> additional Button for standard
430 const String* pUserButtonText // Text for UserButton;
431 // if != 0, the UserButton is created
433 TabDialog( pParent, rResId ),
434 pFrame( pViewFrame ),
435 INI_LIST(pItemSet)
437 Init_Impl( bFmt, pUserButtonText );
440 // -----------------------------------------------------------------------
442 SfxTabDialog::SfxTabDialog
444 /* [Description]
446 Constructor, temporary without Frame
450 Window* pParent, // Parent Window
451 const ResId& rResId, // ResourceId
452 const SfxItemSet* pItemSet, // Itemset with the data;
453 // can be NULL, when Pages are onDemand
454 sal_Bool bEditFmt, // Flag: templates are processed
455 // when yes -> additional Button for standard
456 const String* pUserButtonText // Text for UserButton;
457 // if != 0, the UserButton is created
459 TabDialog( pParent, rResId ),
460 pFrame( 0 ),
461 INI_LIST(pItemSet)
463 Init_Impl( bFmt, pUserButtonText );
464 DBG_WARNING( "Please use the Construtor with the ViewFrame" );
467 // -----------------------------------------------------------------------
469 SfxTabDialog::~SfxTabDialog()
471 // save settings (screen position and current page)
472 SvtViewOptions aDlgOpt( E_TABDIALOG, String::CreateFromInt32( nResId ) );
473 aDlgOpt.SetWindowState(OStringToOUString(GetWindowState(WINDOWSTATE_MASK_POS),RTL_TEXTENCODING_ASCII_US));
474 aDlgOpt.SetPageID( aTabCtrl.GetCurPageId() );
476 const sal_uInt16 nCount = pImpl->pData->Count();
477 for ( sal_uInt16 i = 0; i < nCount; ++i )
479 Data_Impl* pDataObject = pImpl->pData->GetObject(i);
481 if ( pDataObject->pTabPage )
483 // save settings of all pages (user data)
484 pDataObject->pTabPage->FillUserData();
485 String aPageData( pDataObject->pTabPage->GetUserData() );
486 if ( aPageData.Len() )
488 // save settings of all pages (user data)
489 SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
490 aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) );
493 if ( pDataObject->bOnDemand )
494 delete (SfxItemSet*)&pDataObject->pTabPage->GetItemSet();
495 delete pDataObject->pTabPage;
497 delete pDataObject;
500 delete pImpl->pController;
501 delete pImpl->pApplyButton;
502 delete pImpl->pData;
503 delete pImpl;
504 delete pUserBtn;
505 delete pOutSet;
506 delete pExampleSet;
507 delete [] pRanges;
510 // -----------------------------------------------------------------------
512 void SfxTabDialog::Init_Impl( sal_Bool bFmtFlag, const String* pUserButtonText )
514 /* [Description]
516 internal initialization of the dialogue
520 aOKBtn.SetClickHdl( LINK( this, SfxTabDialog, OkHdl ) );
521 aCancelBtn.SetClickHdl( LINK( this, SfxTabDialog, CancelHdl ) );
522 aResetBtn.SetClickHdl( LINK( this, SfxTabDialog, ResetHdl ) );
523 aResetBtn.SetText( String( SfxResId( STR_RESET ) ) );
524 aTabCtrl.SetActivatePageHdl(
525 LINK( this, SfxTabDialog, ActivatePageHdl ) );
526 aTabCtrl.SetDeactivatePageHdl(
527 LINK( this, SfxTabDialog, DeactivatePageHdl ) );
528 aTabCtrl.Show();
529 aOKBtn.Show();
530 aCancelBtn.Show();
531 aHelpBtn.Show();
532 aResetBtn.Show();
533 aResetBtn.SetHelpId( HID_TABDLG_RESET_BTN );
535 if ( pUserBtn )
537 pUserBtn->SetText( *pUserButtonText );
538 pUserBtn->SetClickHdl( LINK( this, SfxTabDialog, UserHdl ) );
539 pUserBtn->Show();
542 /* TODO: Check what is up with bFmt/bFmtFlag. Comment below suggests a
543 different behavior than implemented!! */
544 if ( bFmtFlag )
546 String aStd( SfxResId( STR_STANDARD_SHORTCUT ) );
547 aBaseFmtBtn.SetText( aStd );
548 aBaseFmtBtn.SetClickHdl( LINK( this, SfxTabDialog, BaseFmtHdl ) );
549 aBaseFmtBtn.SetHelpId( HID_TABDLG_STANDARD_BTN );
551 // bFmt = temporary Flag passed on in the Constructor(),
552 // if bFmt == 2, then also sal_True,
553 // additional suppression of the standard button,
554 // after the Initializing set to sal_True again
555 if ( bFmtFlag != 2 )
556 aBaseFmtBtn.Show();
557 else
558 bFmtFlag = sal_True;
561 if ( pSet )
563 pExampleSet = new SfxItemSet( *pSet );
564 pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
567 aOKBtn.SetAccessibleRelationMemberOf( &aOKBtn );
568 aCancelBtn.SetAccessibleRelationMemberOf( &aCancelBtn );
569 aHelpBtn.SetAccessibleRelationMemberOf( &aHelpBtn );
570 aResetBtn.SetAccessibleRelationMemberOf( &aResetBtn );
573 // -----------------------------------------------------------------------
575 void SfxTabDialog::RemoveResetButton()
577 aResetBtn.Hide();
578 pImpl->bHideResetBtn = sal_True;
581 // -----------------------------------------------------------------------
583 short SfxTabDialog::Execute()
585 if ( !aTabCtrl.GetPageCount() )
586 return RET_CANCEL;
587 Start_Impl();
588 return TabDialog::Execute();
591 // -----------------------------------------------------------------------
593 void SfxTabDialog::StartExecuteModal( const Link& rEndDialogHdl )
595 if ( !aTabCtrl.GetPageCount() )
596 return;
597 Start_Impl();
598 TabDialog::StartExecuteModal( rEndDialogHdl );
601 // -----------------------------------------------------------------------
603 void SfxTabDialog::Start( sal_Bool bShow )
605 pImpl->bModal = sal_False;
606 Start_Impl();
608 if ( bShow )
609 Show();
612 // -----------------------------------------------------------------------
614 void SfxTabDialog::SetApplyHandler(const Link& _rHdl)
616 DBG_ASSERT( pImpl->pApplyButton, "SfxTabDialog::GetApplyHandler: no apply button enabled!" );
617 if ( pImpl->pApplyButton )
618 pImpl->pApplyButton->SetClickHdl( _rHdl );
621 // -----------------------------------------------------------------------
623 void SfxTabDialog::EnableApplyButton(sal_Bool bEnable)
625 if ( IsApplyButtonEnabled() == bEnable )
626 // nothing to do
627 return;
629 // create or remove the apply button
630 if ( bEnable )
632 pImpl->pApplyButton = new PushButton( this );
633 // in the z-order, the apply button should be behind the ok button, thus appearing at the right side of it
634 pImpl->pApplyButton->SetZOrder(&aOKBtn, WINDOW_ZORDER_BEHIND);
635 pImpl->pApplyButton->SetText( String( SfxResId( STR_APPLY ) ) );
636 pImpl->pApplyButton->Show();
638 pImpl->pApplyButton->SetHelpId( HID_TABDLG_APPLY_BTN );
640 else
642 delete pImpl->pApplyButton;
643 pImpl->pApplyButton = NULL;
646 // adjust the layout
647 if (IsReallyShown())
648 AdjustLayout();
651 // -----------------------------------------------------------------------
653 sal_Bool SfxTabDialog::IsApplyButtonEnabled() const
655 return ( NULL != pImpl->pApplyButton );
658 // -----------------------------------------------------------------------
660 void SfxTabDialog::Start_Impl()
662 DBG_ASSERT( pImpl->pData->Count() == aTabCtrl.GetPageCount(), "not all pages registered" );
663 sal_uInt16 nActPage = aTabCtrl.GetPageId( 0 );
665 // load old settings, when exists
666 SvtViewOptions aDlgOpt( E_TABDIALOG, String::CreateFromInt32( nResId ) );
667 if ( aDlgOpt.Exists() )
669 SetWindowState(rtl::OUStringToOString(aDlgOpt.GetWindowState().getStr(), RTL_TEXTENCODING_ASCII_US));
671 // initial TabPage from Program/Help/config
672 nActPage = (sal_uInt16)aDlgOpt.GetPageID();
674 if ( USHRT_MAX != nAppPageId )
675 nActPage = nAppPageId;
676 else
678 sal_uInt16 nAutoTabPageId = SFX_APP()->Get_Impl()->nAutoTabPageId;
679 if ( nAutoTabPageId )
680 nActPage = nAutoTabPageId;
683 if ( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nActPage ) )
684 nActPage = aTabCtrl.GetPageId( 0 );
686 else if ( USHRT_MAX != nAppPageId && TAB_PAGE_NOTFOUND != aTabCtrl.GetPagePos( nAppPageId ) )
687 nActPage = nAppPageId;
689 aTabCtrl.SetCurPageId( nActPage );
690 ActivatePageHdl( &aTabCtrl );
693 void SfxTabDialog::AddTabPage( sal_uInt16 nId, sal_Bool bItemsOnDemand )
695 AddTabPage( nId, 0, 0, bItemsOnDemand );
698 void SfxTabDialog::AddTabPage( sal_uInt16 nId, const String &rRiderText, sal_Bool bItemsOnDemand, sal_uInt16 nPos )
700 AddTabPage( nId, rRiderText, 0, 0, bItemsOnDemand, nPos );
703 #ifdef SV_HAS_RIDERBITMAPS
705 void SfxTabDialog::AddTabPage( sal_uInt16 nId, const Bitmap &rRiderBitmap, sal_Bool bItemsOnDemand, sal_uInt16 nPos )
707 AddTabPage( nId, rRiderBitmap, 0, 0, bItemsOnDemand, nPos );
710 #endif
712 // -----------------------------------------------------------------------
714 void SfxTabDialog::AddTabPage
716 /* [Description]
718 Adding a page to the dialogue. Must correspond to a entry in the
719 TabControl in the resource of the dialogue.
723 sal_uInt16 nId, // Page ID
724 CreateTabPage pCreateFunc, // Pointer to the Factory Method
725 GetTabPageRanges pRangesFunc, // Pointer to the Method for quering
726 // Ranges onDemand
727 sal_Bool bItemsOnDemand // indicates whether the set of this page is
728 // requested when created
731 pImpl->pData->Append(
732 new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
735 // -----------------------------------------------------------------------
737 void SfxTabDialog::AddTabPage
739 /* [Description]
741 Add a page to the dialog. The Rider text is passed on, the page has no
742 counterpart in the TabControl in the resource of the dialogue.
746 sal_uInt16 nId,
747 const String& rRiderText,
748 CreateTabPage pCreateFunc,
749 GetTabPageRanges pRangesFunc,
750 sal_Bool bItemsOnDemand,
751 sal_uInt16 nPos
754 DBG_ASSERT( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nId ),
755 "Double Page-Ids in the Tabpage" );
756 aTabCtrl.InsertPage( nId, rRiderText, nPos );
757 pImpl->pData->Append(
758 new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
761 // -----------------------------------------------------------------------
762 #ifdef SV_HAS_RIDERBITMAPS
764 void SfxTabDialog::AddTabPage
766 /* [Description]
768 Add a page to the dialog. The riders bitmap is passed on, the page has no
769 counterpart in the TabControl in the resource of the dialogue.
773 sal_uInt16 nId,
774 const Bitmap &rRiderBitmap,
775 CreateTabPage pCreateFunc,
776 GetTabPageRanges pRangesFunc,
777 sal_Bool bItemsOnDemand,
778 sal_uInt16 nPos
781 DBG_ASSERT( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nId ),
782 "Duplicate Page-Ids in the Tabpage" );
783 aTabCtrl.InsertPage( nId, rRiderBitmap, nPos );
784 pImpl->pData->Append(
785 new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
787 #endif
789 // -----------------------------------------------------------------------
791 void SfxTabDialog::RemoveTabPage( sal_uInt16 nId )
793 /* [Description]
795 Delete the TabPage with ID nId
799 sal_uInt16 nPos = 0;
800 aTabCtrl.RemovePage( nId );
801 Data_Impl* pDataObject = Find( *pImpl->pData, nId, &nPos );
803 if ( pDataObject )
805 if ( pDataObject->pTabPage )
807 pDataObject->pTabPage->FillUserData();
808 String aPageData( pDataObject->pTabPage->GetUserData() );
809 if ( aPageData.Len() )
811 // save settings of this page (user data)
812 SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
813 aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) );
816 if ( pDataObject->bOnDemand )
817 delete (SfxItemSet*)&pDataObject->pTabPage->GetItemSet();
818 delete pDataObject->pTabPage;
821 delete pDataObject;
822 pImpl->pData->Remove( nPos );
824 else
826 SAL_INFO( "sfx2.dialog", "TabPage-Id not known" );
830 // -----------------------------------------------------------------------
832 void SfxTabDialog::PageCreated
834 /* [Description]
836 Default implemetation of the virtual method. This is called immediately
837 after creating a page. Here the dialogue can call the TabPage Method
838 directly.
842 sal_uInt16, // Id of the created page
843 SfxTabPage& // Reference to the created page
848 // -----------------------------------------------------------------------
850 SfxItemSet* SfxTabDialog::GetInputSetImpl()
852 /* [Description]
854 Derived classes may create new storage for the InputSet. This has to be
855 released in the Destructor. To do this, this method must be called.
859 return (SfxItemSet*)pSet;
862 // -----------------------------------------------------------------------
864 SfxTabPage* SfxTabDialog::GetTabPage( sal_uInt16 nPageId ) const
866 /* [Description]
868 Return TabPage with the specified Id.
872 sal_uInt16 nPos = 0;
873 Data_Impl* pDataObject = Find( *pImpl->pData, nPageId, &nPos );
875 if ( pDataObject )
876 return pDataObject->pTabPage;
877 return NULL;
880 // -----------------------------------------------------------------------
882 short SfxTabDialog::Ok()
884 /* [Description]
886 Ok handler for the Dialogue.
887 The OutputSet is created and for each page this or the special OutputSet
888 is set by calling the method <SfxTabPage::FillItemSet(SfxItemSet &)>, to
889 insert the entered data by the user into the set.
891 [Return value]
893 RET_OK: if at least one page has returned from FillItemSet,
894 otherwise RET_CANCEL.
898 pImpl->bInOK = sal_True;
900 if ( !pOutSet )
902 if ( !pExampleSet && pSet )
903 pOutSet = pSet->Clone( sal_False ); // without Items
904 else if ( pExampleSet )
905 pOutSet = new SfxItemSet( *pExampleSet );
907 sal_Bool bModified = sal_False;
909 const sal_uInt16 nCount = pImpl->pData->Count();
911 for ( sal_uInt16 i = 0; i < nCount; ++i )
913 Data_Impl* pDataObject = pImpl->pData->GetObject(i);
914 SfxTabPage* pTabPage = pDataObject->pTabPage;
916 if ( pTabPage )
918 if ( pDataObject->bOnDemand )
920 SfxItemSet& rSet = (SfxItemSet&)pTabPage->GetItemSet();
921 rSet.ClearItem();
922 bModified |= pTabPage->FillItemSet( rSet );
924 else if ( pSet && !pTabPage->HasExchangeSupport() )
926 SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
928 if ( pTabPage->FillItemSet( aTmp ) )
930 bModified |= sal_True;
931 pExampleSet->Put( aTmp );
932 pOutSet->Put( aTmp );
938 if ( pImpl->bModified || ( pOutSet && pOutSet->Count() > 0 ) )
939 bModified |= sal_True;
941 if ( bFmt == 2 )
942 bModified |= sal_True;
943 return bModified ? RET_OK : RET_CANCEL;
946 // -----------------------------------------------------------------------
948 IMPL_LINK_NOARG(SfxTabDialog, CancelHdl)
950 EndDialog( RET_USER_CANCEL );
951 return 0;
954 // -----------------------------------------------------------------------
956 SfxItemSet* SfxTabDialog::CreateInputItemSet( sal_uInt16 )
958 /* [Description]
960 Default implemetation of the virtual Method.
961 This is called when pages create their sets onDenamd.
965 SAL_WARN( "sfx2.dialog", "CreateInputItemSet not implemented" );
966 return new SfxAllItemSet( SFX_APP()->GetPool() );
969 // -----------------------------------------------------------------------
971 const SfxItemSet* SfxTabDialog::GetRefreshedSet()
973 /* [Description]
975 Default implemetation of the virtual Method.
976 This is called, when <SfxTabPage::DeactivatePage(SfxItemSet *)>
977 returns <SfxTabPage::REFRESH_SET>.
981 SAL_INFO ( "sfx2.dialog", "GetRefreshedSet not implemented" );
982 return 0;
985 // -----------------------------------------------------------------------
987 IMPL_LINK_NOARG(SfxTabDialog, OkHdl)
989 /* [Description]
991 Handler of the Ok-Buttons
992 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
993 Returns <SfxTabPage::LEAVE_PAGE>, <SfxTabDialog::Ok()> is called
994 anf the Dialog is ended.
998 pImpl->bInOK = sal_True;
1000 if ( OK_Impl() )
1002 if ( pImpl->bModal )
1003 EndDialog( Ok() );
1004 else
1006 Ok();
1007 Close();
1010 return 0;
1013 // -----------------------------------------------------------------------
1015 bool SfxTabDialog::PrepareLeaveCurrentPage()
1017 sal_uInt16 const nId = aTabCtrl.GetCurPageId();
1018 SfxTabPage* pPage = dynamic_cast<SfxTabPage*> (aTabCtrl.GetTabPage( nId ));
1019 bool bEnd = !pPage;
1021 if ( pPage )
1023 int nRet = SfxTabPage::LEAVE_PAGE;
1024 if ( pSet )
1026 SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1028 if ( pPage->HasExchangeSupport() )
1029 nRet = pPage->DeactivatePage( &aTmp );
1030 else
1031 nRet = pPage->DeactivatePage( NULL );
1033 if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE
1034 && aTmp.Count() )
1036 pExampleSet->Put( aTmp );
1037 pOutSet->Put( aTmp );
1040 else
1041 nRet = pPage->DeactivatePage( NULL );
1042 bEnd = nRet;
1045 return bEnd;
1049 // -----------------------------------------------------------------------
1051 IMPL_LINK_NOARG(SfxTabDialog, UserHdl)
1053 /* [Description]
1055 Handler of the User-Buttons
1056 This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>.
1057 returns this <SfxTabPage::LEAVE_PAGE> and <SfxTabDialog::Ok()> is called.
1058 Then the Dialog is ended with the Return value <SfxTabDialog::Ok()>
1062 if ( PrepareLeaveCurrentPage () )
1064 short nRet = Ok();
1066 if ( RET_OK == nRet )
1067 nRet = RET_USER;
1068 else
1069 nRet = RET_USER_CANCEL;
1070 EndDialog( nRet );
1072 return 0;
1075 // -----------------------------------------------------------------------
1077 IMPL_LINK_NOARG(SfxTabDialog, ResetHdl)
1079 /* [Description]
1081 Handler behind the reset button.
1082 The Current Page is new initialized with their initial data, all the
1083 settings that the user has made on this page are repealed.
1087 const sal_uInt16 nId = aTabCtrl.GetCurPageId();
1088 Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1089 DBG_ASSERT( pDataObject, "Id not known" );
1091 if ( pDataObject->bOnDemand )
1093 // CSet on AIS has problems here, thus separated
1094 const SfxItemSet* pItemSet = &pDataObject->pTabPage->GetItemSet();
1095 pDataObject->pTabPage->Reset( *(SfxItemSet*)pItemSet );
1097 else
1098 pDataObject->pTabPage->Reset( *pSet );
1099 return 0;
1102 // -----------------------------------------------------------------------
1104 IMPL_LINK_NOARG(SfxTabDialog, BaseFmtHdl)
1106 /* [Description]
1108 Handler behind the Standard-Button.
1109 This button is available when editing style sheets. All the set attributes
1110 in the edited stylesheet are deleted.
1114 const sal_uInt16 nId = aTabCtrl.GetCurPageId();
1115 Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1116 DBG_ASSERT( pDataObject, "Id not known" );
1117 bFmt = 2;
1119 if ( pDataObject->fnGetRanges )
1121 if ( !pExampleSet )
1122 pExampleSet = new SfxItemSet( *pSet );
1124 const SfxItemPool* pPool = pSet->GetPool();
1125 const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)();
1126 SfxItemSet aTmpSet( *pExampleSet );
1128 while ( *pTmpRanges )
1130 const sal_uInt16* pU = pTmpRanges + 1;
1132 if ( *pTmpRanges == *pU )
1134 // Range which two identical values -> only set one Item
1135 sal_uInt16 nWh = pPool->GetWhich( *pTmpRanges );
1136 pExampleSet->ClearItem( nWh );
1137 aTmpSet.ClearItem( nWh );
1138 // At the Outset of InvalidateItem,
1139 // so that the change takes effect
1140 pOutSet->InvalidateItem( nWh );
1142 else
1144 // Correct Range with multiple values
1145 sal_uInt16 nTmp = *pTmpRanges, nTmpEnd = *pU;
1146 DBG_ASSERT( nTmp <= nTmpEnd, "Range is sorted the wrong way" );
1148 if ( nTmp > nTmpEnd )
1150 // If really sorted wrongly, then set new
1151 sal_uInt16 nTmp1 = nTmp;
1152 nTmp = nTmpEnd;
1153 nTmpEnd = nTmp1;
1156 while ( nTmp <= nTmpEnd )
1158 // Iterate over the Range and set the Items
1159 sal_uInt16 nWh = pPool->GetWhich( nTmp );
1160 pExampleSet->ClearItem( nWh );
1161 aTmpSet.ClearItem( nWh );
1162 // At the Outset of InvalidateItem,
1163 // so that the change takes effect
1164 pOutSet->InvalidateItem( nWh );
1165 nTmp++;
1168 // Go to the next pair
1169 pTmpRanges += 2;
1171 // Set all Items as new -> the call the current Page Reset()
1172 DBG_ASSERT( pDataObject->pTabPage, "the Page is gone" );
1173 pDataObject->pTabPage->Reset( aTmpSet );
1174 pDataObject->pTabPage->pImpl->mbStandard = sal_True;
1176 return 1;
1179 // -----------------------------------------------------------------------
1181 IMPL_LINK( SfxTabDialog, ActivatePageHdl, TabControl *, pTabCtrl )
1183 /* [Description]
1185 Handler that is called by StarView for switching to a different page.
1186 If the page not exist yet then it is created and the virtual Method
1187 <SfxTabDialog::PageCreated( sal_uInt16, SfxTabPage &)> is called. If the page
1188 exist, then the if possible the <SfxTabPage::Reset(const SfxItemSet &)> or
1189 <SfxTabPage::ActivatePage(const SfxItemSet &)> is called.
1193 sal_uInt16 const nId = pTabCtrl->GetCurPageId();
1195 DBG_ASSERT( pImpl->pData->Count(), "no Pages registered" );
1196 SFX_APP();
1198 // Tab Page schon da?
1199 SfxTabPage* pTabPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId ));
1200 Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1201 DBG_ASSERT( pDataObject, "Id not known" );
1203 // Create TabPage if possible:
1204 if ( !pTabPage )
1206 const SfxItemSet* pTmpSet = 0;
1208 if ( pSet )
1210 if ( bItemsReset && pSet->GetParent() )
1211 pTmpSet = pSet->GetParent();
1212 else
1213 pTmpSet = pSet;
1216 if ( pTmpSet && !pDataObject->bOnDemand )
1217 pTabPage = (pDataObject->fnCreatePage)( pTabCtrl, *pTmpSet );
1218 else
1219 pTabPage = (pDataObject->fnCreatePage)
1220 ( pTabCtrl, *CreateInputItemSet( nId ) );
1221 DBG_ASSERT( NULL == pDataObject->pTabPage, "create TabPage more than once" );
1222 pDataObject->pTabPage = pTabPage;
1224 pDataObject->pTabPage->SetTabDialog( this );
1225 SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
1226 String sUserData;
1227 Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME );
1228 OUString aTemp;
1229 if ( aUserItem >>= aTemp )
1230 sUserData = String( aTemp );
1231 pTabPage->SetUserData( sUserData );
1232 Size aSiz = pTabPage->GetSizePixel();
1234 Size aCtrlSiz = pTabCtrl->GetTabPageSizePixel();
1235 // Only set Size on TabControl when < as TabPage
1236 if ( aCtrlSiz.Width() < aSiz.Width() ||
1237 aCtrlSiz.Height() < aSiz.Height() )
1239 pTabCtrl->SetTabPageSizePixel( aSiz );
1242 PageCreated( nId, *pTabPage );
1244 if ( pDataObject->bOnDemand )
1245 pTabPage->Reset( (SfxItemSet &)pTabPage->GetItemSet() );
1246 else
1247 pTabPage->Reset( *pSet );
1249 pTabCtrl->SetTabPage( nId, pTabPage );
1251 else if ( pDataObject->bRefresh )
1252 pTabPage->Reset( *pSet );
1253 pDataObject->bRefresh = sal_False;
1255 if ( pExampleSet )
1256 pTabPage->ActivatePage( *pExampleSet );
1257 sal_Bool bReadOnly = pTabPage->IsReadOnly();
1258 ( bReadOnly || pImpl->bHideResetBtn ) ? aResetBtn.Hide() : aResetBtn.Show();
1259 return 0;
1262 // -----------------------------------------------------------------------
1264 IMPL_LINK( SfxTabDialog, DeactivatePageHdl, TabControl *, pTabCtrl )
1266 /* [Description]
1268 Handler that is called by StarView before leaving a page.
1270 [Cross-reference]
1272 <SfxTabPage::DeactivatePage(SfxItemSet *)>
1276 sal_uInt16 nId = pTabCtrl->GetCurPageId();
1277 SFX_APP();
1278 SfxTabPage *pPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId ));
1279 DBG_ASSERT( pPage, "no active Page" );
1280 #ifdef DBG_UTIL
1281 Data_Impl* pDataObject = Find( *pImpl->pData, pTabCtrl->GetCurPageId() );
1282 DBG_ASSERT( pDataObject, "no Data structur for current page" );
1283 if ( pPage->HasExchangeSupport() && pDataObject->bOnDemand )
1285 DBG_WARNING( "Data exchange in ItemsOnDemand is not desired!" );
1287 #endif
1289 int nRet = SfxTabPage::LEAVE_PAGE;
1291 if ( !pExampleSet && pPage->HasExchangeSupport() && pSet )
1292 pExampleSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
1294 if ( pSet )
1296 SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1298 if ( pPage->HasExchangeSupport() )
1299 nRet = pPage->DeactivatePage( &aTmp );
1300 else
1301 nRet = pPage->DeactivatePage( NULL );
1302 if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE &&
1303 aTmp.Count() )
1305 pExampleSet->Put( aTmp );
1306 pOutSet->Put( aTmp );
1309 else
1311 if ( pPage->HasExchangeSupport() ) //!!!
1313 if ( !pExampleSet )
1315 SfxItemPool* pPool = pPage->GetItemSet().GetPool();
1316 pExampleSet =
1317 new SfxItemSet( *pPool, GetInputRanges( *pPool ) );
1319 nRet = pPage->DeactivatePage( pExampleSet );
1321 else
1322 nRet = pPage->DeactivatePage( NULL );
1325 if ( nRet & SfxTabPage::REFRESH_SET )
1327 pSet = GetRefreshedSet();
1328 DBG_ASSERT( pSet, "GetRefreshedSet() returns NULL" );
1329 // Flag all Pages as to be initialized as new
1330 const sal_uInt16 nCount = pImpl->pData->Count();
1332 for ( sal_uInt16 i = 0; i < nCount; ++i )
1334 Data_Impl* pObj = (*pImpl->pData)[i];
1336 if ( pObj->pTabPage != pPage ) // Do not refresh own Page anymore
1337 pObj->bRefresh = sal_True;
1338 else
1339 pObj->bRefresh = sal_False;
1342 if ( nRet & SfxTabPage::LEAVE_PAGE )
1343 return sal_True;
1344 else
1345 return sal_False;
1348 // -----------------------------------------------------------------------
1350 void SfxTabDialog::ShowPage( sal_uInt16 nId )
1352 /* [Description]
1354 The TabPage is activated with the specified Id.
1358 aTabCtrl.SetCurPageId( nId );
1359 ActivatePageHdl( &aTabCtrl );
1362 // -----------------------------------------------------------------------
1364 const sal_uInt16* SfxTabDialog::GetInputRanges( const SfxItemPool& rPool )
1366 /* [Description]
1368 Makes the set over the range of all pages of the dialogue. Pages have the
1369 static method for querying their range in AddTabPage, ie deliver their
1370 sets onDemand.
1372 [Return value]
1374 Pointer to a null-terminated array of sal_uInt16. This array belongs to the
1375 dialog and is deleted when the dialogue is destroy.
1377 [Cross-reference]
1379 <SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, sal_Bool)>
1380 <SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1381 <SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1385 if ( pSet )
1387 SAL_WARN( "sfx2.dialog", "Set already exists!" );
1388 return pSet->GetRanges();
1391 if ( pRanges )
1392 return pRanges;
1393 std::vector<sal_uInt16> aUS;
1394 sal_uInt16 nCount = pImpl->pData->Count();
1396 sal_uInt16 i;
1397 for ( i = 0; i < nCount; ++i )
1399 Data_Impl* pDataObject = pImpl->pData->GetObject(i);
1401 if ( pDataObject->fnGetRanges )
1403 const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)();
1404 const sal_uInt16* pIter = pTmpRanges;
1406 sal_uInt16 nLen;
1407 for( nLen = 0; *pIter; ++nLen, ++pIter )
1409 aUS.insert( aUS.end(), pTmpRanges, pTmpRanges + nLen );
1413 //! Remove duplicated Ids?
1415 nCount = aUS.size();
1417 for ( i = 0; i < nCount; ++i )
1418 aUS[i] = rPool.GetWhich( aUS[i] );
1421 // sort
1422 if ( aUS.size() > 1 )
1424 std::sort( aUS.begin(), aUS.end() );
1427 pRanges = new sal_uInt16[aUS.size() + 1];
1428 std::copy( aUS.begin(), aUS.end(), pRanges );
1429 pRanges[aUS.size()] = 0;
1430 return pRanges;
1433 // -----------------------------------------------------------------------
1435 void SfxTabDialog::SetInputSet( const SfxItemSet* pInSet )
1437 /* [Description]
1439 With this method the Input-Set can subsequently be set initally or re-set.
1443 bool bSet = ( pSet != NULL );
1445 pSet = pInSet;
1447 if ( !bSet && !pExampleSet && !pOutSet )
1449 pExampleSet = new SfxItemSet( *pSet );
1450 pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
1454 long SfxTabDialog::Notify( NotifyEvent& rNEvt )
1456 if ( rNEvt.GetType() == EVENT_GETFOCUS )
1458 SfxViewFrame* pViewFrame = GetViewFrame() ? GetViewFrame() : SfxViewFrame::Current();
1459 if ( pViewFrame )
1461 Window* pWindow = rNEvt.GetWindow();
1462 rtl::OString sHelpId;
1463 while ( sHelpId.isEmpty() && pWindow )
1465 sHelpId = pWindow->GetHelpId();
1466 pWindow = pWindow->GetParent();
1469 if ( !sHelpId.isEmpty() )
1470 SfxHelp::OpenHelpAgent( &pViewFrame->GetFrame(), sHelpId );
1474 return TabDialog::Notify( rNEvt );
1477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */