xref: /aoo41x/main/sfx2/source/dialog/tabdlg.cxx (revision d119d52d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26 
27 #include <limits.h>
28 #include <stdlib.h>
29 #include <vcl/msgbox.hxx>
30 #include <unotools/viewoptions.hxx>
31 
32 #define _SVSTDARR_USHORTS
33 #include <svl/svstdarr.hxx>
34 
35 #include "appdata.hxx"
36 #include "sfxtypes.hxx"
37 #include <sfx2/minarray.hxx>
38 #include <sfx2/tabdlg.hxx>
39 #include <sfx2/viewfrm.hxx>
40 #include <sfx2/app.hxx>
41 #include "sfx2/sfxresid.hxx"
42 #include "sfx2/sfxhelp.hxx"
43 #include <sfx2/ctrlitem.hxx>
44 #include <sfx2/bindings.hxx>
45 #include <sfx2/sfxdlg.hxx>
46 #include <sfx2/itemconnect.hxx>
47 
48 #include "dialog.hrc"
49 #include "helpid.hrc"
50 
51 #if ENABLE_LAYOUT_SFX_TABDIALOG
52 #undef TabPage
53 #undef SfxTabPage
54 #define SfxTabPage ::SfxTabPage
55 #undef SfxTabDialog
56 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
57 
58 using namespace ::com::sun::star::uno;
59 using namespace ::rtl;
60 
61 #define USERITEM_NAME			OUString::createFromAscii( "UserItem" )
62 
63 TYPEINIT1(LAYOUT_NS_SFX_TABDIALOG SfxTabDialogItem,SfxSetItem);
64 
65 struct TabPageImpl
66 {
67     sal_Bool                        mbStandard;
68     sfx::ItemConnectionArray    maItemConn;
69     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;
70 
71     TabPageImpl() : mbStandard( sal_False ) {}
72 };
73 
74 NAMESPACE_LAYOUT_SFX_TABDIALOG
75 
76 struct Data_Impl
77 {
78 	sal_uInt16 nId;					 // Die ID
79 	CreateTabPage fnCreatePage;	 // Pointer auf die Factory
80 	GetTabPageRanges fnGetRanges;// Pointer auf die Ranges-Funktion
81 	SfxTabPage* pTabPage;		 // die TabPage selber
82 	sal_Bool bOnDemand;				 // Flag: ItemSet onDemand
83 	sal_Bool bRefresh; 				 // Flag: Seite mu\s neu initialisiert werden
84 
85 	// Konstruktor
86 	Data_Impl( sal_uInt16 Id, CreateTabPage fnPage,
87 			   GetTabPageRanges fnRanges, sal_Bool bDemand ) :
88 
89 		nId			( Id ),
90 		fnCreatePage( fnPage ),
91 		fnGetRanges	( fnRanges ),
92 		pTabPage	( 0 ),
93 		bOnDemand	( bDemand ),
94 		bRefresh	( sal_False )
95 	{
96 		if ( !fnCreatePage  )
97 		{
98 			SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
99 			if ( pFact )
100 			{
101 				fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
102 				fnGetRanges = pFact->GetTabPageRangesFunc( nId );
103 			}
104 		}
105 	}
106 };
107 
108 SfxTabDialogItem::SfxTabDialogItem( const SfxTabDialogItem& rAttr, SfxItemPool* pItemPool )
109     : SfxSetItem( rAttr, pItemPool )
110 {
111 }
112 
113 SfxTabDialogItem::SfxTabDialogItem( sal_uInt16 nId, const SfxItemSet& rItemSet )
114     : SfxSetItem( nId, rItemSet )
115 {
116 }
117 
118 SfxPoolItem* __EXPORT SfxTabDialogItem::Clone(SfxItemPool* pToPool) const
119 {
120     return new SfxTabDialogItem( *this, pToPool );
121 }
122 
123 SfxPoolItem* __EXPORT SfxTabDialogItem::Create(SvStream& /*rStream*/, sal_uInt16 /*nVersion*/) const
124 {
125     DBG_ERROR( "Use it only in UI!" );
126     return NULL;
127 }
128 
129 class SfxTabDialogController : public SfxControllerItem
130 {
131     SfxTabDialog*   pDialog;
132     const SfxItemSet*     pSet;
133 public:
134                     SfxTabDialogController( sal_uInt16 nSlotId, SfxBindings& rBindings, SfxTabDialog* pDlg )
135                         : SfxControllerItem( nSlotId, rBindings )
136                         , pDialog( pDlg )
137                         , pSet( NULL )
138                     {}
139 
140                     ~SfxTabDialogController();
141 
142     DECL_LINK(      Execute_Impl, void* );
143     virtual void    StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState );
144 };
145 
146 SfxTabDialogController::~SfxTabDialogController()
147 {
148     delete pSet;
149 }
150 
151 IMPL_LINK( SfxTabDialogController, Execute_Impl, void*, pVoid )
152 {
153     (void)pVoid; //unused
154     if ( pDialog->OK_Impl() && pDialog->Ok() )
155     {
156         const SfxPoolItem* aItems[2];
157         SfxTabDialogItem aItem( GetId(), *pDialog->GetOutputItemSet() );
158         aItems[0] = &aItem;
159         aItems[1] = NULL;
160         GetBindings().Execute( GetId(), aItems );
161     }
162 
163     return 0;
164 }
165 
166 void SfxTabDialogController::StateChanged( sal_uInt16 /*nSID*/, SfxItemState /*eState*/, const SfxPoolItem* pState )
167 {
168     const SfxSetItem* pSetItem = PTR_CAST( SfxSetItem, pState );
169     if ( pSetItem )
170     {
171         pSet = pDialog->pSet = pSetItem->GetItemSet().Clone();
172         sal_Bool bDialogStarted = sal_False;
173         for ( sal_uInt16 n=0; n<pDialog->aTabCtrl.GetPageCount(); n++ )
174         {
175             sal_uInt16 nPageId = pDialog->aTabCtrl.GetPageId( n );
176             SfxTabPage* pTabPage = dynamic_cast<SfxTabPage*> (pDialog->aTabCtrl.GetTabPage( nPageId ));
177             if ( pTabPage )
178             {
179                 pTabPage->Reset( pSetItem->GetItemSet() );
180                 bDialogStarted = sal_True;
181             }
182         }
183 
184         if ( bDialogStarted )
185             pDialog->Show();
186     }
187     else
188         pDialog->Hide();
189 }
190 
191 DECL_PTRARRAY(SfxTabDlgData_Impl, Data_Impl *, 4,4)
192 
193 struct TabDlg_Impl
194 {
195 	sal_Bool				bModified		: 1,
196 						bModal			: 1,
197 						bInOK			: 1,
198 						bHideResetBtn	: 1;
199 	SfxTabDlgData_Impl*	pData;
200 
201 	PushButton*			pApplyButton;
202     SfxTabDialogController* pController;
203 
204 	TabDlg_Impl( sal_uInt8 nCnt ) :
205 
206 		bModified		( sal_False ),
207 		bModal			( sal_True ),
208 		bInOK			( sal_False ),
209 		bHideResetBtn	( sal_False ),
210 		pData			( new SfxTabDlgData_Impl( nCnt ) ),
211         pApplyButton    ( NULL ),
212         pController     ( NULL )
213 	{}
214 };
215 
216 Data_Impl* Find( SfxTabDlgData_Impl& rArr, sal_uInt16 nId, sal_uInt16* pPos = 0 );
217 
218 Data_Impl* Find( SfxTabDlgData_Impl& rArr, sal_uInt16 nId, sal_uInt16* pPos )
219 {
220 	const sal_uInt16 nCount = rArr.Count();
221 
222 	for ( sal_uInt16 i = 0; i < nCount; ++i )
223 	{
224 		Data_Impl* pObj = rArr[i];
225 
226 		if ( pObj->nId == nId )
227 		{
228 			if ( pPos )
229 				*pPos = i;
230 			return pObj;
231 		}
232 	}
233 	return 0;
234 }
235 
236 #if !ENABLE_LAYOUT_SFX_TABDIALOG
237 
238 void SfxTabPage::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame)
239 {
240     if (pImpl)
241         pImpl->mxFrame = xFrame;
242 }
243 
244 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxTabPage::GetFrame()
245 {
246     if (pImpl)
247         return pImpl->mxFrame;
248     return ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >();
249 }
250 
251 SfxTabPage::SfxTabPage( Window *pParent,
252 						const ResId &rResId, const SfxItemSet &rAttrSet ) :
253 
254 /*  [Beschreibung]
255 
256 	Konstruktor
257 */
258 
259 	TabPage( pParent, rResId ),
260 
261 	pSet				( &rAttrSet ),
262 	bHasExchangeSupport	( sal_False ),
263 	pTabDlg				( NULL ),
264 	pImpl				( new TabPageImpl )
265 
266 {
267 }
268 // -----------------------------------------------------------------------
269 SfxTabPage:: SfxTabPage( Window *pParent, WinBits nStyle, const SfxItemSet &rAttrSet ) :
270 	TabPage(pParent, nStyle),
271 	pSet				( &rAttrSet ),
272 	bHasExchangeSupport	( sal_False ),
273 	pTabDlg				( NULL ),
274 	pImpl				( new TabPageImpl )
275 {
276 }
277 // -----------------------------------------------------------------------
278 
279 SfxTabPage::~SfxTabPage()
280 
281 /*  [Beschreibung]
282 
283 	Destruktor
284 */
285 
286 {
287 #if !ENABLE_LAYOUT
288 	delete pImpl;
289 #endif /* ENABLE_LAYOUT */
290 }
291 
292 // -----------------------------------------------------------------------
293 
294 sal_Bool SfxTabPage::FillItemSet( SfxItemSet& rSet )
295 {
296     return pImpl->maItemConn.DoFillItemSet( rSet, GetItemSet() );
297 }
298 
299 // -----------------------------------------------------------------------
300 
301 void SfxTabPage::Reset( const SfxItemSet& rSet )
302 {
303     pImpl->maItemConn.DoApplyFlags( rSet );
304     pImpl->maItemConn.DoReset( rSet );
305 }
306 
307 // -----------------------------------------------------------------------
308 
309 void SfxTabPage::ActivatePage( const SfxItemSet& )
310 
311 /*  [Beschreibung]
312 
313 	Defaultimplementierung der virtuellen ActivatePage-Methode
314 	Diese wird gerufen, wenn eine Seite des Dialogs den Datenaustausch
315 	zwischen Pages unterst"utzt.
316 
317 	<SfxTabPage::DeactivatePage(SfxItemSet *)>
318 */
319 
320 {
321 }
322 
323 // -----------------------------------------------------------------------
324 
325 int SfxTabPage::DeactivatePage( SfxItemSet* )
326 
327 /*  [Beschreibung]
328 
329 	Defaultimplementierung der virtuellen DeactivatePage-Methode
330 	Diese wird vor dem Verlassen einer Seite durch den Sfx gerufen;
331 	die Anwendung kann "uber den Returnwert steuern,
332 	ob die Seite verlassen werden soll.
333 	Falls die Seite "uber bHasExchangeSupport
334 	anzeigt, da\s sie einen Datenaustausch zwischen Seiten
335 	unterst"utzt, wird ein Pointer auf das Austausch-Set als
336 	Parameter "ubergeben. Dieser nimmt die Daten f"ur den Austausch
337 	entgegen; das Set steht anschlie\send als Parameter in
338 	<SfxTabPage::ActivatePage(const SfxItemSet &)> zur Verf"ugung.
339 
340 	[R"uckgabewert]
341 
342 	LEAVE_PAGE; Verlassen der Seite erlauben
343 */
344 
345 {
346 	return LEAVE_PAGE;
347 }
348 
349 // -----------------------------------------------------------------------
350 
351 void SfxTabPage::FillUserData()
352 
353 /*  [Beschreibung]
354 
355    virtuelle Methode, wird von der Basisklasse im Destruktor gerufen
356    um spezielle Informationen der TabPage in der Ini-Datei zu speichern.
357    Beim "Uberladen muss ein String zusammengestellt werden, der mit
358    <SetUserData()> dann weggeschrieben wird.
359 */
360 
361 {
362 }
363 
364 // -----------------------------------------------------------------------
365 
366 sal_Bool SfxTabPage::IsReadOnly() const
367 
368 /*  [Description]
369 
370 */
371 
372 {
373 	return sal_False;
374 }
375 
376 // -----------------------------------------------------------------------
377 
378 const SfxPoolItem* SfxTabPage::GetItem( const SfxItemSet& rSet, sal_uInt16 nSlot, sal_Bool bDeep )
379 
380 /*  [Beschreibung]
381 
382 	static Methode: hiermit wird der Code der TabPage-Implementierungen
383 	vereinfacht.
384 
385 */
386 
387 {
388 	const SfxItemPool* pPool = rSet.GetPool();
389 	sal_uInt16 nWh = pPool->GetWhich( nSlot, bDeep );
390 	const SfxPoolItem* pItem = 0;
391 #ifdef DEBUG
392 	SfxItemState eState;
393     eState =
394 #endif
395 			rSet.GetItemState( nWh, sal_True, &pItem );  // -Wall required??
396 
397 	if ( !pItem && nWh != nSlot )
398 		pItem = &pPool->GetDefaultItem( nWh );
399 	return pItem;
400 }
401 
402 // -----------------------------------------------------------------------
403 
404 const SfxPoolItem* SfxTabPage::GetOldItem( const SfxItemSet& rSet,
405 										   sal_uInt16 nSlot, sal_Bool bDeep )
406 
407 /*  [Beschreibung]
408 
409 	Diese Methode gibt f"ur Vergleiche den alten Wert eines
410 	Attributs zur"uck.
411 */
412 
413 {
414 	const SfxItemSet& rOldSet = GetItemSet();
415 	sal_uInt16 nWh = GetWhich( nSlot, bDeep );
416 	const SfxPoolItem* pItem = 0;
417 
418     if ( pImpl->mbStandard && rOldSet.GetParent() )
419 		pItem = GetItem( *rOldSet.GetParent(), nSlot );
420 	else if ( rSet.GetParent() &&
421 			  SFX_ITEM_DONTCARE == rSet.GetItemState( nWh ) )
422 		pItem = GetItem( *rSet.GetParent(), nSlot );
423 	else
424 		pItem = GetItem( rOldSet, nSlot );
425 	return pItem;
426 }
427 
428 // -----------------------------------------------------------------------
429 
430 const SfxPoolItem* SfxTabPage::GetExchangeItem( const SfxItemSet& rSet,
431 												sal_uInt16 nSlot )
432 
433 /*  [Beschreibung]
434 
435 	Diese Methode gibt f"ur Vergleiche den alten Wert eines
436 	Attributs zur"uck. Dabei wird ber"ucksichtigt, ob der Dialog
437 	gerade mit OK beendet wurde.
438 */
439 
440 {
441 	if ( pTabDlg && !pTabDlg->IsInOK() && pTabDlg->GetExampleSet() )
442 		return GetItem( *pTabDlg->GetExampleSet(), nSlot );
443 	else
444 		return GetOldItem( rSet, nSlot );
445 }
446 
447 // add CHINA001  begin
448 void SfxTabPage::PageCreated( SfxAllItemSet /*aSet*/ )
449 {
450     DBG_ASSERT(0, "SfxTabPage::PageCreated should not be called");
451 }//CHINA001
452 // add CHINA001 end
453 
454 // -----------------------------------------------------------------------
455 
456 void SfxTabPage::AddItemConnection( sfx::ItemConnectionBase* pConnection )
457 {
458     pImpl->maItemConn.AddConnection( pConnection );
459 }
460 
461 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
462 
463 #if ENABLE_LAYOUT_SFX_TABDIALOG
464 #undef ResId
465 #define ResId(id, foo) #id
466 #undef TabDialog
467 #define TabDialog(parent, res_id) Dialog (parent, "tab-dialog.xml", "tab-dialog")
468 
469 #define aOKBtn(this) aOKBtn (this, "BTN_OK")
470 #undef PushButton
471 #define PushButton(this) layout::PushButton (this, "BTN_USER")
472 #define aCancelBtn(this) aCancelBtn (this, "BTN_CANCEL")
473 #define aHelpBtn(this) aHelpBtn (this, "BTN_HELP")
474 #define aResetBtn(this) aResetBtn (this, "BTN_RESET")
475 #define aBaseFmtBtn(this) aBaseFmtBtn (this, "BTN_BASEFMT")
476 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
477 
478 #define INI_LIST(ItemSetPtr) \
479 	aTabCtrl	( this, ResId(ID_TABCONTROL,*rResId.GetResMgr() ) ),\
480 	aOKBtn		( this ),\
481 	pUserBtn	( pUserButtonText? new PushButton(this): 0 ),\
482 	aCancelBtn	( this ),\
483 	aHelpBtn	( this ),\
484 	aResetBtn	( this ),\
485 	aBaseFmtBtn	( this ),\
486     pSet        ( ItemSetPtr ),\
487 	pOutSet		( 0 ),\
488 	pImpl		( new TabDlg_Impl( (sal_uInt8)aTabCtrl.GetPageCount() ) ), \
489 	pRanges		( 0 ), \
490 	nResId		( rResId.GetId() ), \
491 	nAppPageId	( USHRT_MAX ), \
492 	bItemsReset	( sal_False ),\
493 	bFmt		( bEditFmt ),\
494 	pExampleSet	( 0 )
495 
496 // -----------------------------------------------------------------------
497 
498 SfxTabDialog::SfxTabDialog
499 
500 /*  [Beschreibung]
501 
502 	Konstruktor
503 */
504 
505 (
506 	SfxViewFrame* pViewFrame,		// Frame, zu dem der Dialog geh"ort
507 	Window* pParent,				// Parent-Fenster
508 	const ResId& rResId, 			// ResourceId
509 	const SfxItemSet* pItemSet,		// Itemset mit den Daten;
510 									// kann NULL sein, wenn Pages onDemand
511 	sal_Bool bEditFmt,		// Flag: es werden Vorlagen bearbeitet
512 						// wenn ja -> zus"atzlicher Button f"ur Standard
513 	const String* pUserButtonText 	// Text fuer BenutzerButton;
514 									// wenn != 0, wird der UserButton erzeugt
515 ) :
516 	TabDialog( pParent, rResId ),
517 	pFrame( pViewFrame ),
518     INI_LIST(pItemSet)
519 {
520 	Init_Impl( bFmt, pUserButtonText );
521 }
522 
523 // -----------------------------------------------------------------------
524 
525 SfxTabDialog::SfxTabDialog
526 
527 /*  [Beschreibung]
528 
529 	Konstruktor, tempor"ar ohne Frame
530 */
531 
532 (
533 	Window* pParent,				// Parent-Fenster
534 	const ResId& rResId, 			// ResourceId
535 	const SfxItemSet* pItemSet,		// Itemset mit den Daten; kann NULL sein,
536 									// wenn Pages onDemand
537 	sal_Bool bEditFmt,		// Flag: es werden Vorlagen bearbeitet
538 						// wenn ja -> zus"atzlicher Button f"ur Standard
539 	const String* pUserButtonText 	// Text f"ur BenutzerButton;
540 									// wenn != 0, wird der UserButton erzeugt
541 ) :
542 	TabDialog( pParent, rResId ),
543 	pFrame( 0 ),
544     INI_LIST(pItemSet)
545 {
546 	Init_Impl( bFmt, pUserButtonText );
547 	DBG_WARNING( "bitte den Ctor mit ViewFrame verwenden" );
548 }
549 
550 SfxTabDialog::SfxTabDialog
551 
552 /*  [Beschreibung]
553 
554 	Konstruktor, tempor"ar ohne Frame
555 */
556 
557 (
558 	Window* pParent,				// Parent-Fenster
559 	const ResId& rResId, 			// ResourceId
560     sal_uInt16 nSetId,
561     SfxBindings& rBindings,
562 	sal_Bool bEditFmt,		// Flag: es werden Vorlagen bearbeitet
563 						// wenn ja -> zus"atzlicher Button f"ur Standard
564 	const String* pUserButtonText 	// Text f"ur BenutzerButton;
565 									// wenn != 0, wird der UserButton erzeugt
566 ) :
567 	TabDialog( pParent, rResId ),
568 	pFrame( 0 ),
569     INI_LIST(NULL)
570 {
571     rBindings.ENTERREGISTRATIONS();
572     pImpl->pController = new SfxTabDialogController( nSetId, rBindings, this );
573     rBindings.LEAVEREGISTRATIONS();
574 
575     EnableApplyButton( sal_True );
576     SetApplyHandler( LINK( pImpl->pController, SfxTabDialogController, Execute_Impl ) );
577 
578     rBindings.Invalidate( nSetId );
579     rBindings.Update( nSetId );
580     DBG_ASSERT( pSet, "No ItemSet!" );
581 
582 	Init_Impl( bFmt, pUserButtonText );
583 }
584 
585 // -----------------------------------------------------------------------
586 
587 #if ENABLE_LAYOUT_SFX_TABDIALOG
588 #undef ResId
589 #undef TabDialog
590 #undef aOKBtn
591 #undef PushButton
592 #undef aCancelBtn
593 #undef aHelpBtn
594 #undef aResetBtn
595 #undef aBaseFmtBtn
596 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
597 
598 SfxTabDialog::~SfxTabDialog()
599 {
600 	// save settings (screen position and current page)
601 	SvtViewOptions aDlgOpt( E_TABDIALOG, String::CreateFromInt32( nResId ) );
602 #if !ENABLE_LAYOUT_SFX_TABDIALOG
603 	aDlgOpt.SetWindowState( OUString::createFromAscii( GetWindowState( WINDOWSTATE_MASK_POS ).GetBuffer() ) );
604 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
605 	aDlgOpt.SetPageID( aTabCtrl.GetCurPageId() );
606 
607 	const sal_uInt16 nCount = pImpl->pData->Count();
608 	for ( sal_uInt16 i = 0; i < nCount; ++i )
609 	{
610 		Data_Impl* pDataObject = pImpl->pData->GetObject(i);
611 
612 		if ( pDataObject->pTabPage )
613 		{
614 			// save settings of all pages (user data)
615 			pDataObject->pTabPage->FillUserData();
616 			String aPageData( pDataObject->pTabPage->GetUserData() );
617 			if ( aPageData.Len() )
618 			{
619 				// save settings of all pages (user data)
620 				SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
621 				aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) );
622 			}
623 
624 			if ( pDataObject->bOnDemand )
625 				delete (SfxItemSet*)&pDataObject->pTabPage->GetItemSet();
626 			delete pDataObject->pTabPage;
627 		}
628 		delete pDataObject;
629 	}
630 
631     delete pImpl->pController;
632 	delete pImpl->pApplyButton;
633 	delete pImpl->pData;
634 	delete pImpl;
635 	delete pUserBtn;
636 	delete pOutSet;
637 	delete pExampleSet;
638 	delete [] pRanges;
639 }
640 
641 // -----------------------------------------------------------------------
642 
643 void SfxTabDialog::Init_Impl( sal_Bool bFmtFlag, const String* pUserButtonText )
644 
645 /*  [Beschreibung]
646 
647 	interne Initialisierung des Dialogs
648 */
649 
650 {
651 	aOKBtn.SetClickHdl( LINK( this, SfxTabDialog, OkHdl ) );
652 	aResetBtn.SetClickHdl( LINK( this, SfxTabDialog, ResetHdl ) );
653 	aResetBtn.SetText( String( SfxResId( STR_RESET ) ) );
654 	aTabCtrl.SetActivatePageHdl(
655 			LINK( this, SfxTabDialog, ActivatePageHdl ) );
656 	aTabCtrl.SetDeactivatePageHdl(
657 			LINK( this, SfxTabDialog, DeactivatePageHdl ) );
658 	aTabCtrl.Show();
659 	aOKBtn.Show();
660 	aCancelBtn.Show();
661 	aHelpBtn.Show();
662 	aResetBtn.Show();
663 	aResetBtn.SetHelpId( HID_TABDLG_RESET_BTN );
664 
665 	if ( pUserBtn )
666 	{
667 		pUserBtn->SetText( *pUserButtonText );
668 		pUserBtn->SetClickHdl( LINK( this, SfxTabDialog, UserHdl ) );
669 		pUserBtn->Show();
670 	}
671 
672     /* TODO: Check what is up with bFmt/bFmtFlag. Comment below suggests a
673              different behavior than implemented!! */
674     if ( bFmtFlag )
675 	{
676         String aStd( SfxResId( STR_STANDARD_SHORTCUT ) );
677 		aBaseFmtBtn.SetText( aStd );
678 		aBaseFmtBtn.SetClickHdl( LINK( this, SfxTabDialog, BaseFmtHdl ) );
679 		aBaseFmtBtn.SetHelpId( HID_TABDLG_STANDARD_BTN );
680 
681 		// bFmt = tempor"ares Flag im Ctor() "ubergeben,
682 		// wenn bFmt == 2, dann auch sal_True,
683 		// zus"atzlich Ausblendung vom StandardButton,
684 		// nach der Initialisierung wieder auf sal_True setzen
685 		if ( bFmtFlag != 2 )
686 			aBaseFmtBtn.Show();
687 		else
688 			bFmtFlag = sal_True;
689 	}
690 
691 	if ( pSet )
692 	{
693 		pExampleSet = new SfxItemSet( *pSet );
694 		pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
695 	}
696 
697 	aOKBtn.SetAccessibleRelationMemberOf( &aOKBtn );
698 	aCancelBtn.SetAccessibleRelationMemberOf( &aCancelBtn );
699 	aHelpBtn.SetAccessibleRelationMemberOf( &aHelpBtn );
700 	aResetBtn.SetAccessibleRelationMemberOf( &aResetBtn );
701 }
702 
703 // -----------------------------------------------------------------------
704 
705 void SfxTabDialog::RemoveResetButton()
706 {
707 	aResetBtn.Hide();
708 	pImpl->bHideResetBtn = sal_True;
709 }
710 
711 // -----------------------------------------------------------------------
712 
713 #if ENABLE_LAYOUT_SFX_TABDIALOG
714 #undef TabDialog
715 #define TabDialog Dialog
716 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
717 
718 short SfxTabDialog::Execute()
719 {
720 	if ( !aTabCtrl.GetPageCount() )
721 		return RET_CANCEL;
722 	Start_Impl();
723     return TabDialog::Execute();
724 }
725 
726 // -----------------------------------------------------------------------
727 
728 void SfxTabDialog::StartExecuteModal( const Link& rEndDialogHdl )
729 {
730 #if !ENABLE_LAYOUT_SFX_TABDIALOG
731     if ( !aTabCtrl.GetPageCount() )
732         return;
733     Start_Impl();
734     TabDialog::StartExecuteModal( rEndDialogHdl );
735 #else
736     rEndDialogHdl.IsSet();
737 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
738 }
739 
740 // -----------------------------------------------------------------------
741 
742 void SfxTabDialog::Start( sal_Bool bShow )
743 {
744 	aCancelBtn.SetClickHdl( LINK( this, SfxTabDialog, CancelHdl ) );
745 	pImpl->bModal = sal_False;
746 	Start_Impl();
747 
748 	if ( bShow )
749 		Show();
750 }
751 
752 // -----------------------------------------------------------------------
753 
754 void SfxTabDialog::SetApplyHandler(const Link& _rHdl)
755 {
756 	DBG_ASSERT( pImpl->pApplyButton, "SfxTabDialog::GetApplyHandler: no apply button enabled!" );
757 	if ( pImpl->pApplyButton )
758 		pImpl->pApplyButton->SetClickHdl( _rHdl );
759 }
760 
761 // -----------------------------------------------------------------------
762 
763 Link SfxTabDialog::GetApplyHandler() const
764 {
765 	DBG_ASSERT( pImpl->pApplyButton, "SfxTabDialog::GetApplyHandler: no button enabled!" );
766 	if ( !pImpl->pApplyButton )
767 		return Link();
768 
769 	return pImpl->pApplyButton->GetClickHdl();
770 }
771 
772 // -----------------------------------------------------------------------
773 
774 void SfxTabDialog::EnableApplyButton(sal_Bool bEnable)
775 {
776 	if ( IsApplyButtonEnabled() == bEnable )
777 		// nothing to do
778 		return;
779 
780 	// create or remove the apply button
781 	if ( bEnable )
782 	{
783 		pImpl->pApplyButton = new PushButton( this );
784 #if !ENABLE_LAYOUT_SFX_TABDIALOG
785 		// in the z-order, the apply button should be behind the ok button, thus appearing at the right side of it
786 		pImpl->pApplyButton->SetZOrder(&aOKBtn, WINDOW_ZORDER_BEHIND);
787 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
788 		pImpl->pApplyButton->SetText( String( SfxResId( STR_APPLY ) ) );
789 		pImpl->pApplyButton->Show();
790 
791 		pImpl->pApplyButton->SetHelpId( HID_TABDLG_APPLY_BTN );
792 	}
793 	else
794 	{
795 		delete pImpl->pApplyButton;
796 		pImpl->pApplyButton = NULL;
797 	}
798 
799 #if !ENABLE_LAYOUT_SFX_TABDIALOG
800 	// adjust the layout
801 	if (IsReallyShown())
802 		AdjustLayout();
803 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
804 }
805 
806 // -----------------------------------------------------------------------
807 
808 sal_Bool SfxTabDialog::IsApplyButtonEnabled() const
809 {
810 	return ( NULL != pImpl->pApplyButton );
811 }
812 
813 // -----------------------------------------------------------------------
814 
815 const PushButton* SfxTabDialog::GetApplyButton() const
816 {
817 	return pImpl->pApplyButton;
818 }
819 
820 // -----------------------------------------------------------------------
821 
822 PushButton* SfxTabDialog::GetApplyButton()
823 {
824 	return pImpl->pApplyButton;
825 }
826 
827 // -----------------------------------------------------------------------
828 
829 void SfxTabDialog::Start_Impl()
830 {
831 	DBG_ASSERT( pImpl->pData->Count() == aTabCtrl.GetPageCount(), "not all pages registered" );
832 	sal_uInt16 nActPage = aTabCtrl.GetPageId( 0 );
833 
834 	// load old settings, when exists
835 	SvtViewOptions aDlgOpt( E_TABDIALOG, String::CreateFromInt32( nResId ) );
836 	if ( aDlgOpt.Exists() )
837 	{
838 #if !ENABLE_LAYOUT_SFX_TABDIALOG
839 		SetWindowState( ByteString( aDlgOpt.GetWindowState().getStr(), RTL_TEXTENCODING_ASCII_US ) );
840 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
841 
842 		// initiale TabPage aus Programm/Hilfe/Konfig
843 		nActPage = (sal_uInt16)aDlgOpt.GetPageID();
844 
845 		if ( USHRT_MAX != nAppPageId )
846 			nActPage = nAppPageId;
847 		else
848 		{
849 			sal_uInt16 nAutoTabPageId = SFX_APP()->Get_Impl()->nAutoTabPageId;
850 			if ( nAutoTabPageId )
851 				nActPage = nAutoTabPageId;
852 		}
853 
854 		if ( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nActPage ) )
855 			nActPage = aTabCtrl.GetPageId( 0 );
856 	}
857 	else if ( USHRT_MAX != nAppPageId && TAB_PAGE_NOTFOUND != aTabCtrl.GetPagePos( nAppPageId ) )
858 		nActPage = nAppPageId;
859 
860 	aTabCtrl.SetCurPageId( nActPage );
861 	ActivatePageHdl( &aTabCtrl );
862 }
863 
864 void SfxTabDialog::AddTabPage( sal_uInt16 nId, sal_Bool bItemsOnDemand )
865 {
866 	AddTabPage( nId, 0, 0, bItemsOnDemand );
867 }
868 
869 void SfxTabDialog::AddTabPage( sal_uInt16 nId, const String &rRiderText, sal_Bool bItemsOnDemand, sal_uInt16 nPos )
870 {
871 	AddTabPage( nId, rRiderText, 0, 0, bItemsOnDemand, nPos );
872 }
873 
874 #ifdef SV_HAS_RIDERBITMAPS
875 
876 void SfxTabDialog::AddTabPage( sal_uInt16 nId, const Bitmap &rRiderBitmap, sal_Bool bItemsOnDemand, sal_uInt16 nPos )
877 {
878 	AddTabPage( nId, rRiderBitmap, 0, 0, bItemsOnDemand, nPos );
879 }
880 
881 #endif
882 
883 // -----------------------------------------------------------------------
884 
885 void SfxTabDialog::AddTabPage
886 
887 /*  [Beschreibung]
888 
889 	Hinzuf"ugen einer Seite zu dem Dialog.
890 	Mu\s korrespondieren zu einem entsprechende Eintrag im
891 	TabControl in der Resource des Dialogs.
892 */
893 
894 (
895 	sal_uInt16 nId,						// ID der Seite
896 	CreateTabPage pCreateFunc,		// Pointer auf die Factory-Methode
897 	GetTabPageRanges pRangesFunc, 	// Pointer auf die Methode f"ur das
898 									// Erfragen der Ranges onDemand
899 	sal_Bool bItemsOnDemand				// gibt an, ob das Set dieser Seite beim
900 									// Erzeugen der Seite erfragt wird
901 )
902 {
903 	pImpl->pData->Append(
904 		new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
905 }
906 
907 // -----------------------------------------------------------------------
908 
909 void SfxTabDialog::AddTabPage
910 
911 /*  [Beschreibung]
912 
913 	Hinzuf"ugen einer Seite zu dem Dialog.
914 	Der Ridertext wird "ubergeben, die Seite hat keine Entsprechung im
915 	TabControl in der Resource des Dialogs.
916 */
917 
918 (
919 	sal_uInt16 nId,
920 	const String& rRiderText,
921 	CreateTabPage pCreateFunc,
922 	GetTabPageRanges pRangesFunc,
923 	sal_Bool bItemsOnDemand,
924 	sal_uInt16 nPos
925 )
926 {
927 	DBG_ASSERT( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nId ),
928 				"Doppelte Page-Ids in der Tabpage" );
929 	aTabCtrl.InsertPage( nId, rRiderText, nPos );
930 	pImpl->pData->Append(
931 		new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
932 }
933 
934 // -----------------------------------------------------------------------
935 #ifdef SV_HAS_RIDERBITMAPS
936 
937 void SfxTabDialog::AddTabPage
938 
939 /*  [Beschreibung]
940 
941 	Hinzuf"ugen einer Seite zu dem Dialog.
942 	Die Riderbitmap wird "ubergeben, die Seite hat keine Entsprechung im
943 	TabControl in der Resource des Dialogs.
944 */
945 
946 (
947 	sal_uInt16 nId,
948 	const Bitmap &rRiderBitmap,
949 	CreateTabPage pCreateFunc,
950 	GetTabPageRanges pRangesFunc,
951 	sal_Bool bItemsOnDemand,
952 	sal_uInt16 nPos
953 )
954 {
955 	DBG_ASSERT(	TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nId ),
956 				"Doppelte Page-Ids in der Tabpage" );
957 	aTabCtrl.InsertPage( nId, rRiderBitmap, nPos );
958 	pImpl->pData->Append(
959 		new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
960 }
961 #endif
962 
963 // -----------------------------------------------------------------------
964 
965 void SfxTabDialog::RemoveTabPage( sal_uInt16 nId )
966 
967 /*  [Beschreibung]
968 
969 	L"oschen der TabPage mit der ID nId
970 */
971 
972 {
973 	sal_uInt16 nPos = 0;
974 	aTabCtrl.RemovePage( nId );
975 	Data_Impl* pDataObject = Find( *pImpl->pData, nId, &nPos );
976 
977 	if ( pDataObject )
978 	{
979 		if ( pDataObject->pTabPage )
980 		{
981 			pDataObject->pTabPage->FillUserData();
982 			String aPageData( pDataObject->pTabPage->GetUserData() );
983 			if ( aPageData.Len() )
984 			{
985 				// save settings of this page (user data)
986 				SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
987 				aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) );
988 			}
989 
990 			if ( pDataObject->bOnDemand )
991 				delete (SfxItemSet*)&pDataObject->pTabPage->GetItemSet();
992 			delete pDataObject->pTabPage;
993 		}
994 
995 		delete pDataObject;
996 		pImpl->pData->Remove( nPos );
997 	}
998 	else
999 	{
1000 		DBG_WARNINGFILE( "TabPage-Id nicht bekannt" );
1001 	}
1002 }
1003 
1004 // -----------------------------------------------------------------------
1005 
1006 void SfxTabDialog::PageCreated
1007 
1008 /*  [Beschreibung]
1009 
1010 	Defaultimplemetierung der virtuellen Methode.
1011 	Diese wird unmittelbar nach dem Erzeugen einer Seite gerufen.
1012 	Hier kann der Dialog direkt an der TabPage Methoden rufen.
1013 */
1014 
1015 (
1016 	sal_uInt16,			// Id der erzeugten Seite
1017 	SfxTabPage&		// Referenz auf die erzeugte Seite
1018 )
1019 {
1020 }
1021 
1022 // -----------------------------------------------------------------------
1023 
1024 SfxItemSet* SfxTabDialog::GetInputSetImpl()
1025 
1026 /*  [Beschreibung]
1027 
1028 	Abgeleitete Klassen legen ggf. fuer den InputSet neuen Speicher an.
1029 	Dieser mu\s im Destruktor auch wieder freigegeben werden. Dazu mu\s
1030 	diese Methode gerufen werden.
1031 */
1032 
1033 {
1034 	return (SfxItemSet*)pSet;
1035 }
1036 
1037 // -----------------------------------------------------------------------
1038 
1039 SfxTabPage* SfxTabDialog::GetTabPage( sal_uInt16 nPageId ) const
1040 
1041 /*  [Beschreibung]
1042 
1043 	TabPage mit der "Ubergebenen Id zur"uckgeben.
1044 */
1045 
1046 {
1047 	sal_uInt16 nPos = 0;
1048 	Data_Impl* pDataObject = Find( *pImpl->pData, nPageId, &nPos );
1049 
1050 	if ( pDataObject )
1051 		return pDataObject->pTabPage;
1052 	return NULL;
1053 }
1054 
1055 // -----------------------------------------------------------------------
1056 
1057 sal_Bool SfxTabDialog::IsInOK() const
1058 
1059 /*  [Beschreibung]
1060 
1061 */
1062 
1063 {
1064 	return pImpl->bInOK;
1065 }
1066 
1067 // -----------------------------------------------------------------------
1068 
1069 short SfxTabDialog::Ok()
1070 
1071 /*  [Beschreibung]
1072 
1073 	Ok-Handler des Dialogs
1074 	Das OutputSet wird erstellt und jede Seite wird mit
1075 	dem bzw. ihrem speziellen OutputSet durch Aufruf der Methode
1076 	<SfxTabPage::FillItemSet(SfxItemSet &)> dazu aufgefordert,
1077 	die vom Benuzter eingestellten Daten in das Set zu tun.
1078 
1079 	[R"uckgabewert]
1080 
1081 	RET_OK:	wenn mindestens eine Seite sal_True als Returnwert von
1082 			FillItemSet geliefert hat, sonst RET_CANCEL.
1083 */
1084 
1085 {
1086 	pImpl->bInOK = sal_True;
1087 
1088 	if ( !pOutSet )
1089 	{
1090 		if ( !pExampleSet && pSet )
1091 			pOutSet = pSet->Clone( sal_False );	// ohne Items
1092 		else if ( pExampleSet )
1093 			pOutSet = new SfxItemSet( *pExampleSet );
1094 	}
1095 	sal_Bool bModified = sal_False;
1096 
1097 	const sal_uInt16 nCount = pImpl->pData->Count();
1098 
1099 	for ( sal_uInt16 i = 0; i < nCount; ++i )
1100 	{
1101 		Data_Impl* pDataObject = pImpl->pData->GetObject(i);
1102 		SfxTabPage* pTabPage = pDataObject->pTabPage;
1103 
1104 		if ( pTabPage )
1105 		{
1106 			if ( pDataObject->bOnDemand )
1107 			{
1108 				SfxItemSet& rSet = (SfxItemSet&)pTabPage->GetItemSet();
1109 				rSet.ClearItem();
1110 				bModified |= pTabPage->FillItemSet( rSet );
1111 			}
1112 			else if ( pSet && !pTabPage->HasExchangeSupport() )
1113 			{
1114 				SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1115 
1116 				if ( pTabPage->FillItemSet( aTmp ) )
1117 				{
1118 					bModified |= sal_True;
1119 					pExampleSet->Put( aTmp );
1120 					pOutSet->Put( aTmp );
1121 				}
1122 			}
1123 		}
1124 	}
1125 
1126 	if ( pImpl->bModified || ( pOutSet && pOutSet->Count() > 0 ) )
1127 		bModified |= sal_True;
1128 
1129 	if ( bFmt == 2 )
1130 		bModified |= sal_True;
1131 	return bModified ? RET_OK : RET_CANCEL;
1132 }
1133 
1134 // -----------------------------------------------------------------------
1135 
1136 IMPL_LINK( SfxTabDialog, CancelHdl, Button*, pButton )
1137 {
1138     (void)pButton; //unused
1139     Close();
1140 	return 0;
1141 }
1142 
1143 // -----------------------------------------------------------------------
1144 
1145 SfxItemSet* SfxTabDialog::CreateInputItemSet( sal_uInt16 )
1146 
1147 /*  [Beschreibung]
1148 
1149 	Defaultimplemetierung der virtuellen Methode.
1150 	Diese wird gerufen, wenn Pages ihre Sets onDenamd anlegen
1151 */
1152 
1153 {
1154 	DBG_WARNINGFILE( "CreateInputItemSet nicht implementiert" );
1155 	return new SfxAllItemSet( SFX_APP()->GetPool() );
1156 }
1157 
1158 // -----------------------------------------------------------------------
1159 
1160 const SfxItemSet* SfxTabDialog::GetRefreshedSet()
1161 
1162 /*  [Beschreibung]
1163 
1164 	Defaultimplemetierung der virtuellen Methode.
1165 	Diese wird gerufen, wenn <SfxTabPage::DeactivatePage(SfxItemSet *)>
1166 	<SfxTabPage::REFRESH_SET> liefert.
1167 */
1168 
1169 {
1170 	DBG_ERRORFILE( "GetRefreshedSet nicht implementiert" );
1171 	return 0;
1172 }
1173 
1174 // -----------------------------------------------------------------------
1175 
1176 IMPL_LINK( SfxTabDialog, OkHdl, Button *, EMPTYARG )
1177 
1178 /*  [Beschreibung]
1179 
1180 	Handler des Ok-Buttons
1181 	Dieser ruft f"ur die aktuelle Seite
1182 	<SfxTabPage::DeactivatePage(SfxItemSet *)>.
1183 	Liefert diese <SfxTabPage::LEAVE_PAGE>, wird <SfxTabDialog::Ok()> gerufen
1184 	und so der Dialog beendet.
1185 */
1186 
1187 {
1188 	pImpl->bInOK = sal_True;
1189 
1190 	if ( OK_Impl() )
1191 	{
1192 		if ( pImpl->bModal )
1193 			EndDialog( Ok() );
1194 		else
1195 		{
1196 			Ok();
1197 			Close();
1198 		}
1199 	}
1200 	return 0;
1201 }
1202 
1203 // -----------------------------------------------------------------------
1204 
1205 bool SfxTabDialog::PrepareLeaveCurrentPage()
1206 {
1207 	sal_uInt16 const nId = aTabCtrl.GetCurPageId();
1208 	SfxTabPage* pPage = dynamic_cast<SfxTabPage*> (aTabCtrl.GetTabPage( nId ));
1209 	bool bEnd = !pPage;
1210 
1211 	if ( pPage )
1212 	{
1213 		int nRet = SfxTabPage::LEAVE_PAGE;
1214 		if ( pSet )
1215 		{
1216 			SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1217 
1218 			if ( pPage->HasExchangeSupport() )
1219 				nRet = pPage->DeactivatePage( &aTmp );
1220 			else
1221 				nRet = pPage->DeactivatePage( NULL );
1222 
1223 			if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE
1224 				 && aTmp.Count() )
1225 			{
1226 				pExampleSet->Put( aTmp );
1227 				pOutSet->Put( aTmp );
1228 			}
1229 		}
1230 		else
1231 			nRet = pPage->DeactivatePage( NULL );
1232 		bEnd = nRet;
1233 	}
1234 
1235 	return bEnd;
1236 }
1237 
1238 
1239 // -----------------------------------------------------------------------
1240 
1241 IMPL_LINK( SfxTabDialog, UserHdl, Button *, EMPTYARG )
1242 
1243 /*  [Beschreibung]
1244 
1245 	Handler des User-Buttons
1246 	Dieser ruft f"ur die aktuelle Seite
1247 	<SfxTabPage::DeactivatePage(SfxItemSet *)>.
1248 	Liefert diese <SfxTabPage::LEAVE_PAGE>, wird <SfxTabDialog::Ok()> gerufen.
1249 	Mit dem Return-Wert von <SfxTabDialog::Ok()> wird dann der Dialog beendet.
1250 */
1251 
1252 {
1253 	if ( PrepareLeaveCurrentPage () )
1254 	{
1255 		short nRet = Ok();
1256 
1257 		if ( RET_OK == nRet )
1258 			nRet = RET_USER;
1259 		else
1260 			nRet = RET_USER_CANCEL;
1261 		EndDialog( nRet );
1262 	}
1263 	return 0;
1264 }
1265 
1266 // -----------------------------------------------------------------------
1267 
1268 IMPL_LINK( SfxTabDialog, ResetHdl, Button *, EMPTYARG )
1269 
1270 /*  [Beschreibung]
1271 
1272 	Handler hinter dem Zur"ucksetzen-Button.
1273 	Die aktuelle Page wird mit ihren initialen Daten
1274 	neu initialisiert; alle Einstellungen, die der Benutzer
1275 	auf dieser Seite get"atigt hat, werden aufgehoben.
1276 */
1277 
1278 {
1279     const sal_uInt16 nId = aTabCtrl.GetCurPageId();
1280 	Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1281 	DBG_ASSERT( pDataObject, "Id nicht bekannt" );
1282 
1283 	if ( pDataObject->bOnDemand )
1284 	{
1285 		// CSet auf AIS hat hier Probleme, daher getrennt
1286 		const SfxItemSet* pItemSet = &pDataObject->pTabPage->GetItemSet();
1287 		pDataObject->pTabPage->Reset( *(SfxItemSet*)pItemSet );
1288 	}
1289 	else
1290 		pDataObject->pTabPage->Reset( *pSet );
1291 	return 0;
1292 }
1293 
1294 // -----------------------------------------------------------------------
1295 
1296 IMPL_LINK( SfxTabDialog, BaseFmtHdl, Button *, EMPTYARG )
1297 
1298 /*  [Beschreibung]
1299 
1300 	Handler hinter dem Standard-Button.
1301 	Dieser Button steht beim Bearbeiten von StyleSheets zur Verf"ugung.
1302 	Alle in dem bearbeiteten StyleSheet eingestellten Attribute
1303 	werden gel"oscht.
1304 */
1305 
1306 {
1307 	const sal_uInt16 nId = aTabCtrl.GetCurPageId();
1308 	Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1309 	DBG_ASSERT( pDataObject, "Id nicht bekannt" );
1310 	bFmt = 2;
1311 
1312 	if ( pDataObject->fnGetRanges )
1313 	{
1314 		if ( !pExampleSet )
1315 			pExampleSet = new SfxItemSet( *pSet );
1316 
1317 		const SfxItemPool* pPool = pSet->GetPool();
1318 		const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)();
1319 		SfxItemSet aTmpSet( *pExampleSet );
1320 
1321 		while ( *pTmpRanges )
1322 		{
1323 			const sal_uInt16* pU = pTmpRanges + 1;
1324 
1325 			if ( *pTmpRanges == *pU )
1326 			{
1327 				// Range mit zwei gleichen Werten -> nur ein Item setzen
1328 				sal_uInt16 nWh = pPool->GetWhich( *pTmpRanges );
1329 				pExampleSet->ClearItem( nWh );
1330 				aTmpSet.ClearItem( nWh );
1331 				// am OutSet mit InvalidateItem,
1332 				// damit die "Anderung wirksam wird
1333 				pOutSet->InvalidateItem( nWh );
1334 			}
1335 			else
1336 			{
1337 				// richtiger Range mit mehreren Werten
1338 				sal_uInt16 nTmp = *pTmpRanges, nTmpEnd = *pU;
1339 				DBG_ASSERT( nTmp <= nTmpEnd, "Range ist falsch sortiert" );
1340 
1341 				if ( nTmp > nTmpEnd )
1342 				{
1343 					// wenn wirklich falsch sortiert, dann neu setzen
1344 					sal_uInt16 nTmp1 = nTmp;
1345 					nTmp = nTmpEnd;
1346 					nTmpEnd = nTmp1;
1347 				}
1348 
1349 				while ( nTmp <= nTmpEnd )
1350 				{
1351 					// "uber den Range iterieren, und die Items setzen
1352 					sal_uInt16 nWh = pPool->GetWhich( nTmp );
1353 					pExampleSet->ClearItem( nWh );
1354 					aTmpSet.ClearItem( nWh );
1355 					// am OutSet mit InvalidateItem,
1356 					// damit die "Anderung wirksam wird
1357 					pOutSet->InvalidateItem( nWh );
1358 					nTmp++;
1359 				}
1360 			}
1361 			// zum n"achsten Paar gehen
1362 			pTmpRanges += 2;
1363 		}
1364 		// alle Items neu gesetzt -> dann an der aktuellen Page Reset() rufen
1365 		DBG_ASSERT( pDataObject->pTabPage, "die Page ist weg" );
1366 		pDataObject->pTabPage->Reset( aTmpSet );
1367         pDataObject->pTabPage->pImpl->mbStandard = sal_True;
1368 	}
1369 	return 1;
1370 }
1371 
1372 // -----------------------------------------------------------------------
1373 
1374 #if ENABLE_LAYOUT_SFX_TABDIALOG
1375 #define tabControlWindow pTabCtrl->GetWindow ()
1376 #else /* !ENABLE_LAYOUT_SFX_TABDIALOG */
1377 #define tabControlWindow pTabCtrl
1378 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
1379 
1380 IMPL_LINK( SfxTabDialog, ActivatePageHdl, TabControl *, pTabCtrl )
1381 
1382 /*  [Beschreibung]
1383 
1384 	Handler, der vor dem Umschalten auf eine andere Seite
1385 	durch Starview gerufen wird.
1386 	Existiert die Seite noch nicht, so wird sie erzeugt und
1387 	die virtuelle Methode <SfxTabDialog::PageCreated( sal_uInt16, SfxTabPage &)>
1388 	gerufen. Existiert die Seite bereits, so wird ggf.
1389 	<SfxTabPage::Reset(const SfxItemSet &)> oder
1390 	<SfxTabPage::ActivatePage(const SfxItemSet &)> gerufen.
1391 */
1392 
1393 {
1394     sal_uInt16 const nId = pTabCtrl->GetCurPageId();
1395 
1396 	DBG_ASSERT( pImpl->pData->Count(), "keine Pages angemeldet" );
1397 	SFX_APP();
1398 
1399 	// Tab Page schon da?
1400 	SfxTabPage* pTabPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId ));
1401 	Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1402 	DBG_ASSERT( pDataObject, "Id nicht bekannt" );
1403 
1404 	// ggf. TabPage erzeugen:
1405 	if ( !pTabPage )
1406 	{
1407 #if ENABLE_LAYOUT_SFX_TABDIALOG
1408         if (dynamic_cast<layout SfxTabPage*> (pTabPage))
1409             layout::TabPage::global_parent = pTabCtrl->GetWindow ();
1410 #endif
1411 		const SfxItemSet* pTmpSet = 0;
1412 
1413 		if ( pSet )
1414 		{
1415 			if ( bItemsReset && pSet->GetParent() )
1416 				pTmpSet = pSet->GetParent();
1417 			else
1418 				pTmpSet = pSet;
1419 		}
1420 
1421 		if ( pTmpSet && !pDataObject->bOnDemand )
1422 			pTabPage = (pDataObject->fnCreatePage)( tabControlWindow, *pTmpSet );
1423 		else
1424 			pTabPage = (pDataObject->fnCreatePage)
1425 							( tabControlWindow, *CreateInputItemSet( nId ) );
1426 		DBG_ASSERT( NULL == pDataObject->pTabPage, "create TabPage more than once" );
1427 		pDataObject->pTabPage = pTabPage;
1428 
1429 #if !ENABLE_LAYOUT_SFX_TABDIALOG
1430 		pDataObject->pTabPage->SetTabDialog( this );
1431 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
1432 		SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
1433 		String sUserData;
1434 		Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME );
1435 		OUString aTemp;
1436 		if ( aUserItem >>= aTemp )
1437 			sUserData = String( aTemp );
1438 		pTabPage->SetUserData( sUserData );
1439 		Size aSiz = pTabPage->GetSizePixel();
1440 
1441 #if ENABLE_LAYOUT
1442 		Size optimalSize = pTabPage->GetOptimalSize (WINDOWSIZE_MINIMUM);
1443 #if ENABLE_LAYOUT_SFX_TABDIALOG
1444         if (dynamic_cast<layout SfxTabPage*> (pTabPage))
1445         {
1446             if (optimalSize.Height () && optimalSize.Width ())
1447             {
1448                 optimalSize.Width () = optimalSize.Width ();
1449                 optimalSize.Height () = optimalSize.Height () + 40;
1450             }
1451         }
1452 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
1453         if (optimalSize.Height () > 0 && optimalSize.Width () > 0 )
1454             aSiz = optimalSize;
1455 #endif /* ENABLE_LAYOUT */
1456 
1457 		Size aCtrlSiz = pTabCtrl->GetTabPageSizePixel();
1458 		// Gr"o/se am TabControl nur dann setzen, wenn < als TabPage
1459 		if ( aCtrlSiz.Width() < aSiz.Width() ||
1460 			 aCtrlSiz.Height() < aSiz.Height() )
1461         {
1462 			pTabCtrl->SetTabPageSizePixel( aSiz );
1463         }
1464 
1465 		PageCreated( nId, *pTabPage );
1466 
1467 		if ( pDataObject->bOnDemand )
1468 			pTabPage->Reset( (SfxItemSet &)pTabPage->GetItemSet() );
1469 		else
1470 			pTabPage->Reset( *pSet );
1471 
1472 		pTabCtrl->SetTabPage( nId, pTabPage );
1473 	}
1474 	else if ( pDataObject->bRefresh )
1475 		pTabPage->Reset( *pSet );
1476 	pDataObject->bRefresh = sal_False;
1477 
1478 #if ENABLE_LAYOUT_SFX_TABDIALOG
1479     pTabCtrl->GetPagePos (nId);
1480 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
1481 
1482 	if ( pExampleSet )
1483 		pTabPage->ActivatePage( *pExampleSet );
1484 	sal_Bool bReadOnly = pTabPage->IsReadOnly();
1485 	( bReadOnly || pImpl->bHideResetBtn ) ? aResetBtn.Hide() : aResetBtn.Show();
1486 	return 0;
1487 }
1488 
1489 // -----------------------------------------------------------------------
1490 
1491 IMPL_LINK( SfxTabDialog, DeactivatePageHdl, TabControl *, pTabCtrl )
1492 
1493 /*  [Beschreibung]
1494 
1495 	Handler, der vor dem Verlassen einer Seite durch Starview gerufen wird.
1496 
1497 	[Querverweise]
1498 
1499 	<SfxTabPage::DeactivatePage(SfxItemSet *)>
1500 */
1501 
1502 {
1503 	sal_uInt16 nId = pTabCtrl->GetCurPageId();
1504 	SFX_APP();
1505 	SfxTabPage *pPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId ));
1506 	DBG_ASSERT( pPage, "keine aktive Page" );
1507 #ifdef DBG_UTIL
1508 	Data_Impl* pDataObject = Find( *pImpl->pData, pTabCtrl->GetCurPageId() );
1509 	DBG_ASSERT( pDataObject, "keine Datenstruktur zur aktuellen Seite" );
1510 	if ( pPage->HasExchangeSupport() && pDataObject->bOnDemand )
1511 	{
1512 		DBG_WARNING( "Datenaustausch bei ItemsOnDemand ist nicht gewuenscht!" );
1513 	}
1514 #endif
1515 
1516 	int nRet = SfxTabPage::LEAVE_PAGE;
1517 
1518 	if ( !pExampleSet && pPage->HasExchangeSupport() && pSet )
1519 		pExampleSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
1520 
1521 	if ( pSet )
1522 	{
1523 		SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1524 
1525 		if ( pPage->HasExchangeSupport() )
1526 			nRet = pPage->DeactivatePage( &aTmp );
1527 		else
1528 			nRet = pPage->DeactivatePage( NULL );
1529 //!		else
1530 //!			pPage->FillItemSet( aTmp );
1531 
1532 		if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE &&
1533 			 aTmp.Count() )
1534 		{
1535 			pExampleSet->Put( aTmp );
1536 			pOutSet->Put( aTmp );
1537 		}
1538 	}
1539 	else
1540 	{
1541 		if ( pPage->HasExchangeSupport() ) //!!!
1542 		{
1543 			if ( !pExampleSet )
1544 			{
1545 				SfxItemPool* pPool = pPage->GetItemSet().GetPool();
1546 				pExampleSet =
1547 					new SfxItemSet( *pPool, GetInputRanges( *pPool ) );
1548 			}
1549 			nRet = pPage->DeactivatePage( pExampleSet );
1550 		}
1551 		else
1552 			nRet = pPage->DeactivatePage( NULL );
1553 	}
1554 
1555 	if ( nRet & SfxTabPage::REFRESH_SET )
1556 	{
1557 		pSet = GetRefreshedSet();
1558 		DBG_ASSERT( pSet, "GetRefreshedSet() liefert NULL" );
1559 		// alle Pages als neu zu initialsieren flaggen
1560 		const sal_uInt16 nCount = pImpl->pData->Count();
1561 
1562 		for ( sal_uInt16 i = 0; i < nCount; ++i )
1563 		{
1564 			Data_Impl* pObj = (*pImpl->pData)[i];
1565 
1566 			if ( pObj->pTabPage != pPage ) // eigene Page nicht mehr refreshen
1567 				pObj->bRefresh = sal_True;
1568 			else
1569 				pObj->bRefresh = sal_False;
1570 		}
1571 	}
1572 	if ( nRet & SfxTabPage::LEAVE_PAGE )
1573 		return sal_True;
1574 	else
1575 		return sal_False;
1576 }
1577 
1578 // -----------------------------------------------------------------------
1579 
1580 const SfxItemSet* SfxTabDialog::GetOutputItemSet
1581 
1582 /*  [Beschreibung]
1583 
1584 	Liefert die Pages, die ihre Sets onDemand liefern, das OutputItemSet.
1585 
1586 	[Querverweise]
1587 
1588 	<SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, sal_Bool)>
1589 	<SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1590 	<SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1591 */
1592 
1593 (
1594 	sal_uInt16 nId	// die Id, unter der die Seite bei AddTabPage()
1595 				// hinzugef"ugt wurde.
1596 ) const
1597 {
1598 	Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1599 	DBG_ASSERT( pDataObject, "TabPage nicht gefunden" );
1600 
1601 	if ( pDataObject )
1602 	{
1603 		if ( !pDataObject->pTabPage )
1604 			return NULL;
1605 
1606 		if ( pDataObject->bOnDemand )
1607 			return &pDataObject->pTabPage->GetItemSet();
1608 		// else
1609 		return pOutSet;
1610 	}
1611 	return NULL;
1612 }
1613 
1614 // -----------------------------------------------------------------------
1615 
1616 int SfxTabDialog::FillOutputItemSet()
1617 {
1618 	int nRet = SfxTabPage::LEAVE_PAGE;
1619 	if ( OK_Impl() )
1620 		Ok();
1621 	else
1622 		nRet = SfxTabPage::KEEP_PAGE;
1623 	return nRet;
1624 }
1625 
1626 // -----------------------------------------------------------------------
1627 
1628 #ifdef WNT
1629 int __cdecl TabDlgCmpUS_Impl( const void* p1, const void* p2 )
1630 #else
1631 #if defined(OS2) && defined(ICC)
1632 int _Optlink TabDlgCmpUS_Impl( const void* p1, const void* p2 )
1633 #else
1634 extern "C" int TabDlgCmpUS_Impl( const void* p1, const void* p2 )
1635 #endif
1636 #endif
1637 
1638 /*  [Beschreibung]
1639 
1640 	Vergleichsfunktion f"ur qsort
1641 */
1642 
1643 {
1644 	return *(sal_uInt16*)p1 - *(sal_uInt16*)p2;
1645 }
1646 
1647 // -----------------------------------------------------------------------
1648 
1649 void SfxTabDialog::ShowPage( sal_uInt16 nId )
1650 
1651 /*  [Beschreibung]
1652 
1653 	Es wird die TabPage mit der "ubergebenen Id aktiviert.
1654 */
1655 
1656 {
1657 	aTabCtrl.SetCurPageId( nId );
1658 	ActivatePageHdl( &aTabCtrl );
1659 }
1660 
1661 // -----------------------------------------------------------------------
1662 
1663 const sal_uInt16* SfxTabDialog::GetInputRanges( const SfxItemPool& rPool )
1664 
1665 /*  [Beschreibung]
1666 
1667 	Bildet das Set "uber die Ranges aller Seiten des Dialogs.
1668 	Die Pages m"ussen die statische Methode f"ur das Erfragen ihrer
1669 	Ranges bei AddTabPage angegeben haben, liefern also ihre Sets onDemand.
1670 
1671 	[Querverweise]
1672 
1673 	<SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, sal_Bool)>
1674 	<SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1675 	<SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1676 
1677 	[R"uckgabewert]
1678 
1679 	Pointer auf nullterminiertes Array von USHORTs
1680 	Dieses Array geh"ort dem Dialog und wird beim
1681 	Zerst"oren des Dialogs gel"oscht.
1682 */
1683 
1684 {
1685 	if ( pSet )
1686 	{
1687 		DBG_ERRORFILE( "Set bereits vorhanden!" );
1688 		return pSet->GetRanges();
1689 	}
1690 
1691 	if ( pRanges )
1692 		return pRanges;
1693 	SvUShorts aUS( 16, 16 );
1694 	sal_uInt16 nCount = pImpl->pData->Count();
1695 
1696 	sal_uInt16 i;
1697 	for ( i = 0; i < nCount; ++i )
1698 	{
1699 		Data_Impl* pDataObject = pImpl->pData->GetObject(i);
1700 
1701 		if ( pDataObject->fnGetRanges )
1702 		{
1703 			const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)();
1704 			const sal_uInt16* pIter = pTmpRanges;
1705 
1706 			sal_uInt16 nLen;
1707 			for( nLen = 0; *pIter; ++nLen, ++pIter )
1708 				;
1709 			aUS.Insert( pTmpRanges, nLen, aUS.Count() );
1710 		}
1711 	}
1712 
1713 	//! Doppelte Ids entfernen?
1714 #ifndef TF_POOLABLE
1715 	if ( rPool.HasMap() )
1716 #endif
1717 	{
1718 		nCount = aUS.Count();
1719 
1720 		for ( i = 0; i < nCount; ++i )
1721 			aUS[i] = rPool.GetWhich( aUS[i] );
1722 	}
1723 
1724 	// sortieren
1725 	if ( aUS.Count() > 1 )
1726 		qsort( (void*)aUS.GetData(),
1727 			   aUS.Count(), sizeof(sal_uInt16), TabDlgCmpUS_Impl );
1728 
1729 	// Ranges erzeugen
1730 	//!! Auskommentiert, da fehlerhaft
1731 	/*
1732 	pRanges = new sal_uInt16[aUS.Count() * 2 + 1];
1733 	int j = 0;
1734 	i = 0;
1735 
1736 	while ( i < aUS.Count() )
1737 	{
1738 		pRanges[j++] = aUS[i];
1739 		// aufeinanderfolgende Zahlen
1740 		for( ; i < aUS.Count()-1; ++i )
1741 			if ( aUS[i] + 1 != aUS[i+1] )
1742 				break;
1743 		pRanges[j++] = aUS[i++];
1744 	}
1745 	pRanges[j] = 0;		// terminierende NULL
1746 	*/
1747 
1748 	pRanges = new sal_uInt16[aUS.Count() + 1];
1749 	memcpy(pRanges, aUS.GetData(), sizeof(sal_uInt16) * aUS.Count());
1750 	pRanges[aUS.Count()] = 0;
1751 	return pRanges;
1752 }
1753 
1754 // -----------------------------------------------------------------------
1755 
1756 void SfxTabDialog::SetInputSet( const SfxItemSet* pInSet )
1757 
1758 /*  [Beschreibung]
1759 
1760 	Mit dieser Methode kann nachtr"aglich der Input-Set initial oder
1761 	neu gesetzt werden.
1762 */
1763 
1764 {
1765 	bool bSet = ( pSet != NULL );
1766 
1767 	pSet = pInSet;
1768 
1769 	if ( !bSet && !pExampleSet && !pOutSet )
1770 	{
1771 		pExampleSet = new SfxItemSet( *pSet );
1772 		pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
1773 	}
1774 }
1775 
1776 long SfxTabDialog::Notify( NotifyEvent& rNEvt )
1777 {
1778     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1779 	{
1780         SfxViewFrame* pViewFrame = GetViewFrame() ? GetViewFrame() : SfxViewFrame::Current();
1781         if ( pViewFrame )
1782         {
1783             Window* pWindow = rNEvt.GetWindow();
1784             rtl::OString sHelpId;
1785             while ( !sHelpId.getLength() && pWindow )
1786             {
1787                 sHelpId = pWindow->GetHelpId();
1788                 pWindow = pWindow->GetParent();
1789             }
1790 
1791             if ( sHelpId.getLength() )
1792                 SfxHelp::OpenHelpAgent( &pViewFrame->GetFrame(), sHelpId );
1793         }
1794 	}
1795 
1796     return TabDialog::Notify( rNEvt );
1797 }
1798 
1799 END_NAMESPACE_LAYOUT_SFX_TABDIALOG
1800