xref: /aoo42x/main/sfx2/source/dialog/tabdlg.cxx (revision e4c43045)
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 // IAccessibility2 implementation 2009
752 	if ( IsVisible() && ( !HasChildPathFocus() || HasFocus() ) )
753 		GrabFocusToFirstControl();
754 }
755 
756 // -----------------------------------------------------------------------
757 
758 void SfxTabDialog::SetApplyHandler(const Link& _rHdl)
759 {
760 	DBG_ASSERT( pImpl->pApplyButton, "SfxTabDialog::GetApplyHandler: no apply button enabled!" );
761 	if ( pImpl->pApplyButton )
762 		pImpl->pApplyButton->SetClickHdl( _rHdl );
763 }
764 
765 // -----------------------------------------------------------------------
766 
767 Link SfxTabDialog::GetApplyHandler() const
768 {
769 	DBG_ASSERT( pImpl->pApplyButton, "SfxTabDialog::GetApplyHandler: no button enabled!" );
770 	if ( !pImpl->pApplyButton )
771 		return Link();
772 
773 	return pImpl->pApplyButton->GetClickHdl();
774 }
775 
776 // -----------------------------------------------------------------------
777 
778 void SfxTabDialog::EnableApplyButton(sal_Bool bEnable)
779 {
780 	if ( IsApplyButtonEnabled() == bEnable )
781 		// nothing to do
782 		return;
783 
784 	// create or remove the apply button
785 	if ( bEnable )
786 	{
787 		pImpl->pApplyButton = new PushButton( this );
788 #if !ENABLE_LAYOUT_SFX_TABDIALOG
789 		// in the z-order, the apply button should be behind the ok button, thus appearing at the right side of it
790 		pImpl->pApplyButton->SetZOrder(&aOKBtn, WINDOW_ZORDER_BEHIND);
791 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
792 		pImpl->pApplyButton->SetText( String( SfxResId( STR_APPLY ) ) );
793 		pImpl->pApplyButton->Show();
794 
795 		pImpl->pApplyButton->SetHelpId( HID_TABDLG_APPLY_BTN );
796 	}
797 	else
798 	{
799 		delete pImpl->pApplyButton;
800 		pImpl->pApplyButton = NULL;
801 	}
802 
803 #if !ENABLE_LAYOUT_SFX_TABDIALOG
804 	// adjust the layout
805 	if (IsReallyShown())
806 		AdjustLayout();
807 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
808 }
809 
810 // -----------------------------------------------------------------------
811 
812 sal_Bool SfxTabDialog::IsApplyButtonEnabled() const
813 {
814 	return ( NULL != pImpl->pApplyButton );
815 }
816 
817 // -----------------------------------------------------------------------
818 
819 const PushButton* SfxTabDialog::GetApplyButton() const
820 {
821 	return pImpl->pApplyButton;
822 }
823 
824 // -----------------------------------------------------------------------
825 
826 PushButton* SfxTabDialog::GetApplyButton()
827 {
828 	return pImpl->pApplyButton;
829 }
830 
831 // -----------------------------------------------------------------------
832 
833 void SfxTabDialog::Start_Impl()
834 {
835 	DBG_ASSERT( pImpl->pData->Count() == aTabCtrl.GetPageCount(), "not all pages registered" );
836 	sal_uInt16 nActPage = aTabCtrl.GetPageId( 0 );
837 
838 	// load old settings, when exists
839 	SvtViewOptions aDlgOpt( E_TABDIALOG, String::CreateFromInt32( nResId ) );
840 	if ( aDlgOpt.Exists() )
841 	{
842 #if !ENABLE_LAYOUT_SFX_TABDIALOG
843 		SetWindowState( ByteString( aDlgOpt.GetWindowState().getStr(), RTL_TEXTENCODING_ASCII_US ) );
844 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
845 
846 		// initiale TabPage aus Programm/Hilfe/Konfig
847 		nActPage = (sal_uInt16)aDlgOpt.GetPageID();
848 
849 		if ( USHRT_MAX != nAppPageId )
850 			nActPage = nAppPageId;
851 		else
852 		{
853 			sal_uInt16 nAutoTabPageId = SFX_APP()->Get_Impl()->nAutoTabPageId;
854 			if ( nAutoTabPageId )
855 				nActPage = nAutoTabPageId;
856 		}
857 
858 		if ( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nActPage ) )
859 			nActPage = aTabCtrl.GetPageId( 0 );
860 	}
861 	else if ( USHRT_MAX != nAppPageId && TAB_PAGE_NOTFOUND != aTabCtrl.GetPagePos( nAppPageId ) )
862 		nActPage = nAppPageId;
863 
864 	aTabCtrl.SetCurPageId( nActPage );
865 	ActivatePageHdl( &aTabCtrl );
866 }
867 
868 void SfxTabDialog::AddTabPage( sal_uInt16 nId, sal_Bool bItemsOnDemand )
869 {
870 	AddTabPage( nId, 0, 0, bItemsOnDemand );
871 }
872 
873 void SfxTabDialog::AddTabPage( sal_uInt16 nId, const String &rRiderText, sal_Bool bItemsOnDemand, sal_uInt16 nPos )
874 {
875 	AddTabPage( nId, rRiderText, 0, 0, bItemsOnDemand, nPos );
876 }
877 
878 #ifdef SV_HAS_RIDERBITMAPS
879 
880 void SfxTabDialog::AddTabPage( sal_uInt16 nId, const Bitmap &rRiderBitmap, sal_Bool bItemsOnDemand, sal_uInt16 nPos )
881 {
882 	AddTabPage( nId, rRiderBitmap, 0, 0, bItemsOnDemand, nPos );
883 }
884 
885 #endif
886 
887 // -----------------------------------------------------------------------
888 
889 void SfxTabDialog::AddTabPage
890 
891 /*  [Beschreibung]
892 
893 	Hinzuf"ugen einer Seite zu dem Dialog.
894 	Mu\s korrespondieren zu einem entsprechende Eintrag im
895 	TabControl in der Resource des Dialogs.
896 */
897 
898 (
899 	sal_uInt16 nId,						// ID der Seite
900 	CreateTabPage pCreateFunc,		// Pointer auf die Factory-Methode
901 	GetTabPageRanges pRangesFunc, 	// Pointer auf die Methode f"ur das
902 									// Erfragen der Ranges onDemand
903 	sal_Bool bItemsOnDemand				// gibt an, ob das Set dieser Seite beim
904 									// Erzeugen der Seite erfragt wird
905 )
906 {
907 	pImpl->pData->Append(
908 		new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
909 }
910 
911 // -----------------------------------------------------------------------
912 
913 void SfxTabDialog::AddTabPage
914 
915 /*  [Beschreibung]
916 
917 	Hinzuf"ugen einer Seite zu dem Dialog.
918 	Der Ridertext wird "ubergeben, die Seite hat keine Entsprechung im
919 	TabControl in der Resource des Dialogs.
920 */
921 
922 (
923 	sal_uInt16 nId,
924 	const String& rRiderText,
925 	CreateTabPage pCreateFunc,
926 	GetTabPageRanges pRangesFunc,
927 	sal_Bool bItemsOnDemand,
928 	sal_uInt16 nPos
929 )
930 {
931 	DBG_ASSERT( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nId ),
932 				"Doppelte Page-Ids in der Tabpage" );
933 	aTabCtrl.InsertPage( nId, rRiderText, nPos );
934 	pImpl->pData->Append(
935 		new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
936 }
937 
938 // -----------------------------------------------------------------------
939 #ifdef SV_HAS_RIDERBITMAPS
940 
941 void SfxTabDialog::AddTabPage
942 
943 /*  [Beschreibung]
944 
945 	Hinzuf"ugen einer Seite zu dem Dialog.
946 	Die Riderbitmap wird "ubergeben, die Seite hat keine Entsprechung im
947 	TabControl in der Resource des Dialogs.
948 */
949 
950 (
951 	sal_uInt16 nId,
952 	const Bitmap &rRiderBitmap,
953 	CreateTabPage pCreateFunc,
954 	GetTabPageRanges pRangesFunc,
955 	sal_Bool bItemsOnDemand,
956 	sal_uInt16 nPos
957 )
958 {
959 	DBG_ASSERT(	TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nId ),
960 				"Doppelte Page-Ids in der Tabpage" );
961 	aTabCtrl.InsertPage( nId, rRiderBitmap, nPos );
962 	pImpl->pData->Append(
963 		new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) );
964 }
965 #endif
966 
967 // -----------------------------------------------------------------------
968 
969 void SfxTabDialog::RemoveTabPage( sal_uInt16 nId )
970 
971 /*  [Beschreibung]
972 
973 	L"oschen der TabPage mit der ID nId
974 */
975 
976 {
977 	sal_uInt16 nPos = 0;
978 	aTabCtrl.RemovePage( nId );
979 	Data_Impl* pDataObject = Find( *pImpl->pData, nId, &nPos );
980 
981 	if ( pDataObject )
982 	{
983 		if ( pDataObject->pTabPage )
984 		{
985 			pDataObject->pTabPage->FillUserData();
986 			String aPageData( pDataObject->pTabPage->GetUserData() );
987 			if ( aPageData.Len() )
988 			{
989 				// save settings of this page (user data)
990 				SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
991 				aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) );
992 			}
993 
994 			if ( pDataObject->bOnDemand )
995 				delete (SfxItemSet*)&pDataObject->pTabPage->GetItemSet();
996 			delete pDataObject->pTabPage;
997 		}
998 
999 		delete pDataObject;
1000 		pImpl->pData->Remove( nPos );
1001 	}
1002 	else
1003 	{
1004 		DBG_WARNINGFILE( "TabPage-Id nicht bekannt" );
1005 	}
1006 }
1007 
1008 // -----------------------------------------------------------------------
1009 
1010 void SfxTabDialog::PageCreated
1011 
1012 /*  [Beschreibung]
1013 
1014 	Defaultimplemetierung der virtuellen Methode.
1015 	Diese wird unmittelbar nach dem Erzeugen einer Seite gerufen.
1016 	Hier kann der Dialog direkt an der TabPage Methoden rufen.
1017 */
1018 
1019 (
1020 	sal_uInt16,			// Id der erzeugten Seite
1021 	SfxTabPage&		// Referenz auf die erzeugte Seite
1022 )
1023 {
1024 }
1025 
1026 // -----------------------------------------------------------------------
1027 
1028 SfxItemSet* SfxTabDialog::GetInputSetImpl()
1029 
1030 /*  [Beschreibung]
1031 
1032 	Abgeleitete Klassen legen ggf. fuer den InputSet neuen Speicher an.
1033 	Dieser mu\s im Destruktor auch wieder freigegeben werden. Dazu mu\s
1034 	diese Methode gerufen werden.
1035 */
1036 
1037 {
1038 	return (SfxItemSet*)pSet;
1039 }
1040 
1041 // -----------------------------------------------------------------------
1042 
1043 SfxTabPage* SfxTabDialog::GetTabPage( sal_uInt16 nPageId ) const
1044 
1045 /*  [Beschreibung]
1046 
1047 	TabPage mit der "Ubergebenen Id zur"uckgeben.
1048 */
1049 
1050 {
1051 	sal_uInt16 nPos = 0;
1052 	Data_Impl* pDataObject = Find( *pImpl->pData, nPageId, &nPos );
1053 
1054 	if ( pDataObject )
1055 		return pDataObject->pTabPage;
1056 	return NULL;
1057 }
1058 
1059 // -----------------------------------------------------------------------
1060 
1061 sal_Bool SfxTabDialog::IsInOK() const
1062 
1063 /*  [Beschreibung]
1064 
1065 */
1066 
1067 {
1068 	return pImpl->bInOK;
1069 }
1070 
1071 // -----------------------------------------------------------------------
1072 
1073 short SfxTabDialog::Ok()
1074 
1075 /*  [Beschreibung]
1076 
1077 	Ok-Handler des Dialogs
1078 	Das OutputSet wird erstellt und jede Seite wird mit
1079 	dem bzw. ihrem speziellen OutputSet durch Aufruf der Methode
1080 	<SfxTabPage::FillItemSet(SfxItemSet &)> dazu aufgefordert,
1081 	die vom Benuzter eingestellten Daten in das Set zu tun.
1082 
1083 	[R"uckgabewert]
1084 
1085 	RET_OK:	wenn mindestens eine Seite sal_True als Returnwert von
1086 			FillItemSet geliefert hat, sonst RET_CANCEL.
1087 */
1088 
1089 {
1090 	pImpl->bInOK = sal_True;
1091 
1092 	if ( !pOutSet )
1093 	{
1094 		if ( !pExampleSet && pSet )
1095 			pOutSet = pSet->Clone( sal_False );	// ohne Items
1096 		else if ( pExampleSet )
1097 			pOutSet = new SfxItemSet( *pExampleSet );
1098 	}
1099 	sal_Bool bModified = sal_False;
1100 
1101 	const sal_uInt16 nCount = pImpl->pData->Count();
1102 
1103 	for ( sal_uInt16 i = 0; i < nCount; ++i )
1104 	{
1105 		Data_Impl* pDataObject = pImpl->pData->GetObject(i);
1106 		SfxTabPage* pTabPage = pDataObject->pTabPage;
1107 
1108 		if ( pTabPage )
1109 		{
1110 			if ( pDataObject->bOnDemand )
1111 			{
1112 				SfxItemSet& rSet = (SfxItemSet&)pTabPage->GetItemSet();
1113 				rSet.ClearItem();
1114 				bModified |= pTabPage->FillItemSet( rSet );
1115 			}
1116 			else if ( pSet && !pTabPage->HasExchangeSupport() )
1117 			{
1118 				SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1119 
1120 				if ( pTabPage->FillItemSet( aTmp ) )
1121 				{
1122 					bModified |= sal_True;
1123 					pExampleSet->Put( aTmp );
1124 					pOutSet->Put( aTmp );
1125 				}
1126 			}
1127 		}
1128 	}
1129 
1130 	if ( pImpl->bModified || ( pOutSet && pOutSet->Count() > 0 ) )
1131 		bModified |= sal_True;
1132 
1133 	if ( bFmt == 2 )
1134 		bModified |= sal_True;
1135 	return bModified ? RET_OK : RET_CANCEL;
1136 }
1137 
1138 // -----------------------------------------------------------------------
1139 
1140 IMPL_LINK( SfxTabDialog, CancelHdl, Button*, pButton )
1141 {
1142     (void)pButton; //unused
1143     Close();
1144 	return 0;
1145 }
1146 
1147 // -----------------------------------------------------------------------
1148 
1149 SfxItemSet* SfxTabDialog::CreateInputItemSet( sal_uInt16 )
1150 
1151 /*  [Beschreibung]
1152 
1153 	Defaultimplemetierung der virtuellen Methode.
1154 	Diese wird gerufen, wenn Pages ihre Sets onDenamd anlegen
1155 */
1156 
1157 {
1158 	DBG_WARNINGFILE( "CreateInputItemSet nicht implementiert" );
1159 	return new SfxAllItemSet( SFX_APP()->GetPool() );
1160 }
1161 
1162 // -----------------------------------------------------------------------
1163 
1164 const SfxItemSet* SfxTabDialog::GetRefreshedSet()
1165 
1166 /*  [Beschreibung]
1167 
1168 	Defaultimplemetierung der virtuellen Methode.
1169 	Diese wird gerufen, wenn <SfxTabPage::DeactivatePage(SfxItemSet *)>
1170 	<SfxTabPage::REFRESH_SET> liefert.
1171 */
1172 
1173 {
1174 	DBG_ERRORFILE( "GetRefreshedSet nicht implementiert" );
1175 	return 0;
1176 }
1177 
1178 // -----------------------------------------------------------------------
1179 
1180 IMPL_LINK( SfxTabDialog, OkHdl, Button *, EMPTYARG )
1181 
1182 /*  [Beschreibung]
1183 
1184 	Handler des Ok-Buttons
1185 	Dieser ruft f"ur die aktuelle Seite
1186 	<SfxTabPage::DeactivatePage(SfxItemSet *)>.
1187 	Liefert diese <SfxTabPage::LEAVE_PAGE>, wird <SfxTabDialog::Ok()> gerufen
1188 	und so der Dialog beendet.
1189 */
1190 
1191 {
1192 	pImpl->bInOK = sal_True;
1193 
1194 	if ( OK_Impl() )
1195 	{
1196 		if ( pImpl->bModal )
1197 			EndDialog( Ok() );
1198 		else
1199 		{
1200 			Ok();
1201 			Close();
1202 		}
1203 	}
1204 	return 0;
1205 }
1206 
1207 // -----------------------------------------------------------------------
1208 
1209 bool SfxTabDialog::PrepareLeaveCurrentPage()
1210 {
1211 	sal_uInt16 const nId = aTabCtrl.GetCurPageId();
1212 	SfxTabPage* pPage = dynamic_cast<SfxTabPage*> (aTabCtrl.GetTabPage( nId ));
1213 	bool bEnd = !pPage;
1214 
1215 	if ( pPage )
1216 	{
1217 		int nRet = SfxTabPage::LEAVE_PAGE;
1218 		if ( pSet )
1219 		{
1220 			SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1221 
1222 			if ( pPage->HasExchangeSupport() )
1223 				nRet = pPage->DeactivatePage( &aTmp );
1224 			else
1225 				nRet = pPage->DeactivatePage( NULL );
1226 
1227 			if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE
1228 				 && aTmp.Count() )
1229 			{
1230 				pExampleSet->Put( aTmp );
1231 				pOutSet->Put( aTmp );
1232 			}
1233 		}
1234 		else
1235 			nRet = pPage->DeactivatePage( NULL );
1236 		bEnd = nRet;
1237 	}
1238 
1239 	return bEnd;
1240 }
1241 
1242 
1243 // -----------------------------------------------------------------------
1244 
1245 IMPL_LINK( SfxTabDialog, UserHdl, Button *, EMPTYARG )
1246 
1247 /*  [Beschreibung]
1248 
1249 	Handler des User-Buttons
1250 	Dieser ruft f"ur die aktuelle Seite
1251 	<SfxTabPage::DeactivatePage(SfxItemSet *)>.
1252 	Liefert diese <SfxTabPage::LEAVE_PAGE>, wird <SfxTabDialog::Ok()> gerufen.
1253 	Mit dem Return-Wert von <SfxTabDialog::Ok()> wird dann der Dialog beendet.
1254 */
1255 
1256 {
1257 	if ( PrepareLeaveCurrentPage () )
1258 	{
1259 		short nRet = Ok();
1260 
1261 		if ( RET_OK == nRet )
1262 			nRet = RET_USER;
1263 		else
1264 			nRet = RET_USER_CANCEL;
1265 		EndDialog( nRet );
1266 	}
1267 	return 0;
1268 }
1269 
1270 // -----------------------------------------------------------------------
1271 
1272 IMPL_LINK( SfxTabDialog, ResetHdl, Button *, EMPTYARG )
1273 
1274 /*  [Beschreibung]
1275 
1276 	Handler hinter dem Zur"ucksetzen-Button.
1277 	Die aktuelle Page wird mit ihren initialen Daten
1278 	neu initialisiert; alle Einstellungen, die der Benutzer
1279 	auf dieser Seite get"atigt hat, werden aufgehoben.
1280 */
1281 
1282 {
1283     const sal_uInt16 nId = aTabCtrl.GetCurPageId();
1284 	Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1285 	DBG_ASSERT( pDataObject, "Id nicht bekannt" );
1286 
1287 	if ( pDataObject->bOnDemand )
1288 	{
1289 		// CSet auf AIS hat hier Probleme, daher getrennt
1290 		const SfxItemSet* pItemSet = &pDataObject->pTabPage->GetItemSet();
1291 		pDataObject->pTabPage->Reset( *(SfxItemSet*)pItemSet );
1292 	}
1293 	else
1294 		pDataObject->pTabPage->Reset( *pSet );
1295 	return 0;
1296 }
1297 
1298 // -----------------------------------------------------------------------
1299 
1300 IMPL_LINK( SfxTabDialog, BaseFmtHdl, Button *, EMPTYARG )
1301 
1302 /*  [Beschreibung]
1303 
1304 	Handler hinter dem Standard-Button.
1305 	Dieser Button steht beim Bearbeiten von StyleSheets zur Verf"ugung.
1306 	Alle in dem bearbeiteten StyleSheet eingestellten Attribute
1307 	werden gel"oscht.
1308 */
1309 
1310 {
1311 	const sal_uInt16 nId = aTabCtrl.GetCurPageId();
1312 	Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1313 	DBG_ASSERT( pDataObject, "Id nicht bekannt" );
1314 	bFmt = 2;
1315 
1316 	if ( pDataObject->fnGetRanges )
1317 	{
1318 		if ( !pExampleSet )
1319 			pExampleSet = new SfxItemSet( *pSet );
1320 
1321 		const SfxItemPool* pPool = pSet->GetPool();
1322 		const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)();
1323 		SfxItemSet aTmpSet( *pExampleSet );
1324 
1325 		while ( *pTmpRanges )
1326 		{
1327 			const sal_uInt16* pU = pTmpRanges + 1;
1328 
1329 			if ( *pTmpRanges == *pU )
1330 			{
1331 				// Range mit zwei gleichen Werten -> nur ein Item setzen
1332 				sal_uInt16 nWh = pPool->GetWhich( *pTmpRanges );
1333 				pExampleSet->ClearItem( nWh );
1334 				aTmpSet.ClearItem( nWh );
1335 				// am OutSet mit InvalidateItem,
1336 				// damit die "Anderung wirksam wird
1337 				pOutSet->InvalidateItem( nWh );
1338 			}
1339 			else
1340 			{
1341 				// richtiger Range mit mehreren Werten
1342 				sal_uInt16 nTmp = *pTmpRanges, nTmpEnd = *pU;
1343 				DBG_ASSERT( nTmp <= nTmpEnd, "Range ist falsch sortiert" );
1344 
1345 				if ( nTmp > nTmpEnd )
1346 				{
1347 					// wenn wirklich falsch sortiert, dann neu setzen
1348 					sal_uInt16 nTmp1 = nTmp;
1349 					nTmp = nTmpEnd;
1350 					nTmpEnd = nTmp1;
1351 				}
1352 
1353 				while ( nTmp <= nTmpEnd )
1354 				{
1355 					// "uber den Range iterieren, und die Items setzen
1356 					sal_uInt16 nWh = pPool->GetWhich( nTmp );
1357 					pExampleSet->ClearItem( nWh );
1358 					aTmpSet.ClearItem( nWh );
1359 					// am OutSet mit InvalidateItem,
1360 					// damit die "Anderung wirksam wird
1361 					pOutSet->InvalidateItem( nWh );
1362 					nTmp++;
1363 				}
1364 			}
1365 			// zum n"achsten Paar gehen
1366 			pTmpRanges += 2;
1367 		}
1368 		// alle Items neu gesetzt -> dann an der aktuellen Page Reset() rufen
1369 		DBG_ASSERT( pDataObject->pTabPage, "die Page ist weg" );
1370 		pDataObject->pTabPage->Reset( aTmpSet );
1371         pDataObject->pTabPage->pImpl->mbStandard = sal_True;
1372 	}
1373 	return 1;
1374 }
1375 
1376 // -----------------------------------------------------------------------
1377 
1378 #if ENABLE_LAYOUT_SFX_TABDIALOG
1379 #define tabControlWindow pTabCtrl->GetWindow ()
1380 #else /* !ENABLE_LAYOUT_SFX_TABDIALOG */
1381 #define tabControlWindow pTabCtrl
1382 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
1383 
1384 IMPL_LINK( SfxTabDialog, ActivatePageHdl, TabControl *, pTabCtrl )
1385 
1386 /*  [Beschreibung]
1387 
1388 	Handler, der vor dem Umschalten auf eine andere Seite
1389 	durch Starview gerufen wird.
1390 	Existiert die Seite noch nicht, so wird sie erzeugt und
1391 	die virtuelle Methode <SfxTabDialog::PageCreated( sal_uInt16, SfxTabPage &)>
1392 	gerufen. Existiert die Seite bereits, so wird ggf.
1393 	<SfxTabPage::Reset(const SfxItemSet &)> oder
1394 	<SfxTabPage::ActivatePage(const SfxItemSet &)> gerufen.
1395 */
1396 
1397 {
1398     sal_uInt16 const nId = pTabCtrl->GetCurPageId();
1399 
1400 	DBG_ASSERT( pImpl->pData->Count(), "keine Pages angemeldet" );
1401 	SFX_APP();
1402 
1403 	// Tab Page schon da?
1404 	SfxTabPage* pTabPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId ));
1405 	Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1406 	DBG_ASSERT( pDataObject, "Id nicht bekannt" );
1407 
1408 	// ggf. TabPage erzeugen:
1409 	if ( !pTabPage )
1410 	{
1411 #if ENABLE_LAYOUT_SFX_TABDIALOG
1412         if (dynamic_cast<layout SfxTabPage*> (pTabPage))
1413             layout::TabPage::global_parent = pTabCtrl->GetWindow ();
1414 #endif
1415 		const SfxItemSet* pTmpSet = 0;
1416 
1417 		if ( pSet )
1418 		{
1419 			if ( bItemsReset && pSet->GetParent() )
1420 				pTmpSet = pSet->GetParent();
1421 			else
1422 				pTmpSet = pSet;
1423 		}
1424 
1425 		if ( pTmpSet && !pDataObject->bOnDemand )
1426 			pTabPage = (pDataObject->fnCreatePage)( tabControlWindow, *pTmpSet );
1427 		else
1428 			pTabPage = (pDataObject->fnCreatePage)
1429 							( tabControlWindow, *CreateInputItemSet( nId ) );
1430 		DBG_ASSERT( NULL == pDataObject->pTabPage, "create TabPage more than once" );
1431 		pDataObject->pTabPage = pTabPage;
1432 
1433 #if !ENABLE_LAYOUT_SFX_TABDIALOG
1434 		pDataObject->pTabPage->SetTabDialog( this );
1435 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
1436 		SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
1437 		String sUserData;
1438 		Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME );
1439 		OUString aTemp;
1440 		if ( aUserItem >>= aTemp )
1441 			sUserData = String( aTemp );
1442 		pTabPage->SetUserData( sUserData );
1443 		Size aSiz = pTabPage->GetSizePixel();
1444 
1445 #if ENABLE_LAYOUT
1446 		Size optimalSize = pTabPage->GetOptimalSize (WINDOWSIZE_MINIMUM);
1447 #if ENABLE_LAYOUT_SFX_TABDIALOG
1448         if (dynamic_cast<layout SfxTabPage*> (pTabPage))
1449         {
1450             if (optimalSize.Height () && optimalSize.Width ())
1451             {
1452                 optimalSize.Width () = optimalSize.Width ();
1453                 optimalSize.Height () = optimalSize.Height () + 40;
1454             }
1455         }
1456 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
1457         if (optimalSize.Height () > 0 && optimalSize.Width () > 0 )
1458             aSiz = optimalSize;
1459 #endif /* ENABLE_LAYOUT */
1460 
1461 		Size aCtrlSiz = pTabCtrl->GetTabPageSizePixel();
1462 		// Gr"o/se am TabControl nur dann setzen, wenn < als TabPage
1463 		if ( aCtrlSiz.Width() < aSiz.Width() ||
1464 			 aCtrlSiz.Height() < aSiz.Height() )
1465         {
1466 			pTabCtrl->SetTabPageSizePixel( aSiz );
1467         }
1468 
1469 		PageCreated( nId, *pTabPage );
1470 
1471 		if ( pDataObject->bOnDemand )
1472 			pTabPage->Reset( (SfxItemSet &)pTabPage->GetItemSet() );
1473 		else
1474 			pTabPage->Reset( *pSet );
1475 
1476 		pTabCtrl->SetTabPage( nId, pTabPage );
1477 	}
1478 	else if ( pDataObject->bRefresh )
1479 		pTabPage->Reset( *pSet );
1480 	pDataObject->bRefresh = sal_False;
1481 
1482 #if ENABLE_LAYOUT_SFX_TABDIALOG
1483     pTabCtrl->GetPagePos (nId);
1484 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
1485 
1486 	if ( pExampleSet )
1487 		pTabPage->ActivatePage( *pExampleSet );
1488 	sal_Bool bReadOnly = pTabPage->IsReadOnly();
1489 	( bReadOnly || pImpl->bHideResetBtn ) ? aResetBtn.Hide() : aResetBtn.Show();
1490 	return 0;
1491 }
1492 
1493 // -----------------------------------------------------------------------
1494 
1495 IMPL_LINK( SfxTabDialog, DeactivatePageHdl, TabControl *, pTabCtrl )
1496 
1497 /*  [Beschreibung]
1498 
1499 	Handler, der vor dem Verlassen einer Seite durch Starview gerufen wird.
1500 
1501 	[Querverweise]
1502 
1503 	<SfxTabPage::DeactivatePage(SfxItemSet *)>
1504 */
1505 
1506 {
1507 	sal_uInt16 nId = pTabCtrl->GetCurPageId();
1508 	SFX_APP();
1509 	SfxTabPage *pPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId ));
1510 	DBG_ASSERT( pPage, "keine aktive Page" );
1511 #ifdef DBG_UTIL
1512 	Data_Impl* pDataObject = Find( *pImpl->pData, pTabCtrl->GetCurPageId() );
1513 	DBG_ASSERT( pDataObject, "keine Datenstruktur zur aktuellen Seite" );
1514 	if ( pPage->HasExchangeSupport() && pDataObject->bOnDemand )
1515 	{
1516 		DBG_WARNING( "Datenaustausch bei ItemsOnDemand ist nicht gewuenscht!" );
1517 	}
1518 #endif
1519 
1520 	int nRet = SfxTabPage::LEAVE_PAGE;
1521 
1522 	if ( !pExampleSet && pPage->HasExchangeSupport() && pSet )
1523 		pExampleSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
1524 
1525 	if ( pSet )
1526 	{
1527 		SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() );
1528 
1529 		if ( pPage->HasExchangeSupport() )
1530 			nRet = pPage->DeactivatePage( &aTmp );
1531 		else
1532 			nRet = pPage->DeactivatePage( NULL );
1533 //!		else
1534 //!			pPage->FillItemSet( aTmp );
1535 
1536 		if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE &&
1537 			 aTmp.Count() )
1538 		{
1539 			pExampleSet->Put( aTmp );
1540 			pOutSet->Put( aTmp );
1541 		}
1542 	}
1543 	else
1544 	{
1545 		if ( pPage->HasExchangeSupport() ) //!!!
1546 		{
1547 			if ( !pExampleSet )
1548 			{
1549 				SfxItemPool* pPool = pPage->GetItemSet().GetPool();
1550 				pExampleSet =
1551 					new SfxItemSet( *pPool, GetInputRanges( *pPool ) );
1552 			}
1553 			nRet = pPage->DeactivatePage( pExampleSet );
1554 		}
1555 		else
1556 			nRet = pPage->DeactivatePage( NULL );
1557 	}
1558 
1559 	if ( nRet & SfxTabPage::REFRESH_SET )
1560 	{
1561 		pSet = GetRefreshedSet();
1562 		DBG_ASSERT( pSet, "GetRefreshedSet() liefert NULL" );
1563 		// alle Pages als neu zu initialsieren flaggen
1564 		const sal_uInt16 nCount = pImpl->pData->Count();
1565 
1566 		for ( sal_uInt16 i = 0; i < nCount; ++i )
1567 		{
1568 			Data_Impl* pObj = (*pImpl->pData)[i];
1569 
1570 			if ( pObj->pTabPage != pPage ) // eigene Page nicht mehr refreshen
1571 				pObj->bRefresh = sal_True;
1572 			else
1573 				pObj->bRefresh = sal_False;
1574 		}
1575 	}
1576 	if ( nRet & SfxTabPage::LEAVE_PAGE )
1577 		return sal_True;
1578 	else
1579 		return sal_False;
1580 }
1581 
1582 // -----------------------------------------------------------------------
1583 
1584 const SfxItemSet* SfxTabDialog::GetOutputItemSet
1585 
1586 /*  [Beschreibung]
1587 
1588 	Liefert die Pages, die ihre Sets onDemand liefern, das OutputItemSet.
1589 
1590 	[Querverweise]
1591 
1592 	<SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, sal_Bool)>
1593 	<SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1594 	<SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1595 */
1596 
1597 (
1598 	sal_uInt16 nId	// die Id, unter der die Seite bei AddTabPage()
1599 				// hinzugef"ugt wurde.
1600 ) const
1601 {
1602 	Data_Impl* pDataObject = Find( *pImpl->pData, nId );
1603 	DBG_ASSERT( pDataObject, "TabPage nicht gefunden" );
1604 
1605 	if ( pDataObject )
1606 	{
1607 		if ( !pDataObject->pTabPage )
1608 			return NULL;
1609 
1610 		if ( pDataObject->bOnDemand )
1611 			return &pDataObject->pTabPage->GetItemSet();
1612 		// else
1613 		return pOutSet;
1614 	}
1615 	return NULL;
1616 }
1617 
1618 // -----------------------------------------------------------------------
1619 
1620 int SfxTabDialog::FillOutputItemSet()
1621 {
1622 	int nRet = SfxTabPage::LEAVE_PAGE;
1623 	if ( OK_Impl() )
1624 		Ok();
1625 	else
1626 		nRet = SfxTabPage::KEEP_PAGE;
1627 	return nRet;
1628 }
1629 
1630 // -----------------------------------------------------------------------
1631 
1632 #ifdef WNT
1633 int __cdecl TabDlgCmpUS_Impl( const void* p1, const void* p2 )
1634 #else
1635 #if defined(OS2) && defined(ICC)
1636 int _Optlink TabDlgCmpUS_Impl( const void* p1, const void* p2 )
1637 #else
1638 extern "C" int TabDlgCmpUS_Impl( const void* p1, const void* p2 )
1639 #endif
1640 #endif
1641 
1642 /*  [Beschreibung]
1643 
1644 	Vergleichsfunktion f"ur qsort
1645 */
1646 
1647 {
1648 	return *(sal_uInt16*)p1 - *(sal_uInt16*)p2;
1649 }
1650 
1651 // -----------------------------------------------------------------------
1652 
1653 void SfxTabDialog::ShowPage( sal_uInt16 nId )
1654 
1655 /*  [Beschreibung]
1656 
1657 	Es wird die TabPage mit der "ubergebenen Id aktiviert.
1658 */
1659 
1660 {
1661 	aTabCtrl.SetCurPageId( nId );
1662 	ActivatePageHdl( &aTabCtrl );
1663 }
1664 
1665 // -----------------------------------------------------------------------
1666 
1667 const sal_uInt16* SfxTabDialog::GetInputRanges( const SfxItemPool& rPool )
1668 
1669 /*  [Beschreibung]
1670 
1671 	Bildet das Set "uber die Ranges aller Seiten des Dialogs.
1672 	Die Pages m"ussen die statische Methode f"ur das Erfragen ihrer
1673 	Ranges bei AddTabPage angegeben haben, liefern also ihre Sets onDemand.
1674 
1675 	[Querverweise]
1676 
1677 	<SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, sal_Bool)>
1678 	<SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1679 	<SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, sal_Bool, sal_uInt16)>
1680 
1681 	[R"uckgabewert]
1682 
1683 	Pointer auf nullterminiertes Array von USHORTs
1684 	Dieses Array geh"ort dem Dialog und wird beim
1685 	Zerst"oren des Dialogs gel"oscht.
1686 */
1687 
1688 {
1689 	if ( pSet )
1690 	{
1691 		DBG_ERRORFILE( "Set bereits vorhanden!" );
1692 		return pSet->GetRanges();
1693 	}
1694 
1695 	if ( pRanges )
1696 		return pRanges;
1697 	SvUShorts aUS( 16, 16 );
1698 	sal_uInt16 nCount = pImpl->pData->Count();
1699 
1700 	sal_uInt16 i;
1701 	for ( i = 0; i < nCount; ++i )
1702 	{
1703 		Data_Impl* pDataObject = pImpl->pData->GetObject(i);
1704 
1705 		if ( pDataObject->fnGetRanges )
1706 		{
1707 			const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)();
1708 			const sal_uInt16* pIter = pTmpRanges;
1709 
1710 			sal_uInt16 nLen;
1711 			for( nLen = 0; *pIter; ++nLen, ++pIter )
1712 				;
1713 			aUS.Insert( pTmpRanges, nLen, aUS.Count() );
1714 		}
1715 	}
1716 
1717 	//! Doppelte Ids entfernen?
1718 #ifndef TF_POOLABLE
1719 	if ( rPool.HasMap() )
1720 #endif
1721 	{
1722 		nCount = aUS.Count();
1723 
1724 		for ( i = 0; i < nCount; ++i )
1725 			aUS[i] = rPool.GetWhich( aUS[i] );
1726 	}
1727 
1728 	// sortieren
1729 	if ( aUS.Count() > 1 )
1730 		qsort( (void*)aUS.GetData(),
1731 			   aUS.Count(), sizeof(sal_uInt16), TabDlgCmpUS_Impl );
1732 
1733 	// Ranges erzeugen
1734 	//!! Auskommentiert, da fehlerhaft
1735 	/*
1736 	pRanges = new sal_uInt16[aUS.Count() * 2 + 1];
1737 	int j = 0;
1738 	i = 0;
1739 
1740 	while ( i < aUS.Count() )
1741 	{
1742 		pRanges[j++] = aUS[i];
1743 		// aufeinanderfolgende Zahlen
1744 		for( ; i < aUS.Count()-1; ++i )
1745 			if ( aUS[i] + 1 != aUS[i+1] )
1746 				break;
1747 		pRanges[j++] = aUS[i++];
1748 	}
1749 	pRanges[j] = 0;		// terminierende NULL
1750 	*/
1751 
1752 	pRanges = new sal_uInt16[aUS.Count() + 1];
1753 	memcpy(pRanges, aUS.GetData(), sizeof(sal_uInt16) * aUS.Count());
1754 	pRanges[aUS.Count()] = 0;
1755 	return pRanges;
1756 }
1757 
1758 // -----------------------------------------------------------------------
1759 
1760 void SfxTabDialog::SetInputSet( const SfxItemSet* pInSet )
1761 
1762 /*  [Beschreibung]
1763 
1764 	Mit dieser Methode kann nachtr"aglich der Input-Set initial oder
1765 	neu gesetzt werden.
1766 */
1767 
1768 {
1769 	bool bSet = ( pSet != NULL );
1770 
1771 	pSet = pInSet;
1772 
1773 	if ( !bSet && !pExampleSet && !pOutSet )
1774 	{
1775 		pExampleSet = new SfxItemSet( *pSet );
1776 		pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
1777 	}
1778 }
1779 
1780 long SfxTabDialog::Notify( NotifyEvent& rNEvt )
1781 {
1782     if ( rNEvt.GetType() == EVENT_GETFOCUS )
1783 	{
1784         SfxViewFrame* pViewFrame = GetViewFrame() ? GetViewFrame() : SfxViewFrame::Current();
1785         if ( pViewFrame )
1786         {
1787             Window* pWindow = rNEvt.GetWindow();
1788             rtl::OString sHelpId;
1789             while ( !sHelpId.getLength() && pWindow )
1790             {
1791                 sHelpId = pWindow->GetHelpId();
1792                 pWindow = pWindow->GetParent();
1793             }
1794 
1795             if ( sHelpId.getLength() )
1796                 SfxHelp::OpenHelpAgent( &pViewFrame->GetFrame(), sHelpId );
1797         }
1798 	}
1799 
1800     return TabDialog::Notify( rNEvt );
1801 }
1802 
1803 END_NAMESPACE_LAYOUT_SFX_TABDIALOG
1804