xref: /trunk/main/sfx2/source/dialog/tabdlg.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include <limits.h>
32 #include <stdlib.h>
33 #include <vcl/msgbox.hxx>
34 #include <unotools/viewoptions.hxx>
35 
36 #define _SVSTDARR_USHORTS
37 #include <svl/svstdarr.hxx>
38 
39 #include "appdata.hxx"
40 #include "sfxtypes.hxx"
41 #include <sfx2/minarray.hxx>
42 #include <sfx2/tabdlg.hxx>
43 #include <sfx2/viewfrm.hxx>
44 #include <sfx2/app.hxx>
45 #include "sfx2/sfxresid.hxx"
46 #include "sfx2/sfxhelp.hxx"
47 #include <sfx2/ctrlitem.hxx>
48 #include <sfx2/bindings.hxx>
49 #include <sfx2/sfxdlg.hxx>
50 #include <sfx2/itemconnect.hxx>
51 
52 #include "dialog.hrc"
53 #include "helpid.hrc"
54 
55 #if ENABLE_LAYOUT_SFX_TABDIALOG
56 #undef TabPage
57 #undef SfxTabPage
58 #define SfxTabPage ::SfxTabPage
59 #undef SfxTabDialog
60 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
61 
62 using namespace ::com::sun::star::uno;
63 using namespace ::rtl;
64 
65 #define USERITEM_NAME           OUString::createFromAscii( "UserItem" )
66 
67 TYPEINIT1(LAYOUT_NS_SFX_TABDIALOG SfxTabDialogItem,SfxSetItem);
68 
69 struct TabPageImpl
70 {
71     sal_Bool                        mbStandard;
72     sfx::ItemConnectionArray    maItemConn;
73     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;
74 
75     TabPageImpl() : mbStandard( sal_False ) {}
76 };
77 
78 NAMESPACE_LAYOUT_SFX_TABDIALOG
79 
80 struct Data_Impl
81 {
82     sal_uInt16 nId;                  // Die ID
83     CreateTabPage fnCreatePage;  // Pointer auf die Factory
84     GetTabPageRanges fnGetRanges;// Pointer auf die Ranges-Funktion
85     SfxTabPage* pTabPage;        // die TabPage selber
86     sal_Bool bOnDemand;              // Flag: ItemSet onDemand
87     sal_Bool bRefresh;               // Flag: Seite mu\s neu initialisiert werden
88 
89     // Konstruktor
90     Data_Impl( sal_uInt16 Id, CreateTabPage fnPage,
91                GetTabPageRanges fnRanges, sal_Bool bDemand ) :
92 
93         nId         ( Id ),
94         fnCreatePage( fnPage ),
95         fnGetRanges ( fnRanges ),
96         pTabPage    ( 0 ),
97         bOnDemand   ( bDemand ),
98         bRefresh    ( sal_False )
99     {
100         if ( !fnCreatePage  )
101         {
102             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
103             if ( pFact )
104             {
105                 fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
106                 fnGetRanges = pFact->GetTabPageRangesFunc( nId );
107             }
108         }
109     }
110 };
111 
112 SfxTabDialogItem::SfxTabDialogItem( const SfxTabDialogItem& rAttr, SfxItemPool* pItemPool )
113     : SfxSetItem( rAttr, pItemPool )
114 {
115 }
116 
117 SfxTabDialogItem::SfxTabDialogItem( sal_uInt16 nId, const SfxItemSet& rItemSet )
118     : SfxSetItem( nId, rItemSet )
119 {
120 }
121 
122 SfxPoolItem* __EXPORT SfxTabDialogItem::Clone(SfxItemPool* pToPool) const
123 {
124     return new SfxTabDialogItem( *this, pToPool );
125 }
126 
127 SfxPoolItem* __EXPORT SfxTabDialogItem::Create(SvStream& /*rStream*/, sal_uInt16 /*nVersion*/) const
128 {
129     DBG_ERROR( "Use it only in UI!" );
130     return NULL;
131 }
132 
133 class SfxTabDialogController : public SfxControllerItem
134 {
135     SfxTabDialog*   pDialog;
136     const SfxItemSet*     pSet;
137 public:
138                     SfxTabDialogController( sal_uInt16 nSlotId, SfxBindings& rBindings, SfxTabDialog* pDlg )
139                         : SfxControllerItem( nSlotId, rBindings )
140                         , pDialog( pDlg )
141                         , pSet( NULL )
142                     {}
143 
144                     ~SfxTabDialogController();
145 
146     DECL_LINK(      Execute_Impl, void* );
147     virtual void    StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState );
148 };
149 
150 SfxTabDialogController::~SfxTabDialogController()
151 {
152     delete pSet;
153 }
154 
155 IMPL_LINK( SfxTabDialogController, Execute_Impl, void*, pVoid )
156 {
157     (void)pVoid; //unused
158     if ( pDialog->OK_Impl() && pDialog->Ok() )
159     {
160         const SfxPoolItem* aItems[2];
161         SfxTabDialogItem aItem( GetId(), *pDialog->GetOutputItemSet() );
162         aItems[0] = &aItem;
163         aItems[1] = NULL;
164         GetBindings().Execute( GetId(), aItems );
165     }
166 
167     return 0;
168 }
169 
170 void SfxTabDialogController::StateChanged( sal_uInt16 /*nSID*/, SfxItemState /*eState*/, const SfxPoolItem* pState )
171 {
172     const SfxSetItem* pSetItem = PTR_CAST( SfxSetItem, pState );
173     if ( pSetItem )
174     {
175         pSet = pDialog->pSet = pSetItem->GetItemSet().Clone();
176         sal_Bool bDialogStarted = sal_False;
177         for ( sal_uInt16 n=0; n<pDialog->aTabCtrl.GetPageCount(); n++ )
178         {
179             sal_uInt16 nPageId = pDialog->aTabCtrl.GetPageId( n );
180             SfxTabPage* pTabPage = dynamic_cast<SfxTabPage*> (pDialog->aTabCtrl.GetTabPage( nPageId ));
181             if ( pTabPage )
182             {
183                 pTabPage->Reset( pSetItem->GetItemSet() );
184                 bDialogStarted = sal_True;
185             }
186         }
187 
188         if ( bDialogStarted )
189             pDialog->Show();
190     }
191     else
192         pDialog->Hide();
193 }
194 
195 DECL_PTRARRAY(SfxTabDlgData_Impl, Data_Impl *, 4,4)
196 
197 struct TabDlg_Impl
198 {
199     sal_Bool                bModified       : 1,
200                         bModal          : 1,
201                         bInOK           : 1,
202                         bHideResetBtn   : 1;
203     SfxTabDlgData_Impl* pData;
204 
205     PushButton*         pApplyButton;
206     SfxTabDialogController* pController;
207 
208     TabDlg_Impl( sal_uInt8 nCnt ) :
209 
210         bModified       ( sal_False ),
211         bModal          ( sal_True ),
212         bInOK           ( sal_False ),
213         bHideResetBtn   ( sal_False ),
214         pData           ( new SfxTabDlgData_Impl( nCnt ) ),
215         pApplyButton    ( NULL ),
216         pController     ( NULL )
217     {}
218 };
219 
220 Data_Impl* Find( SfxTabDlgData_Impl& rArr, sal_uInt16 nId, sal_uInt16* pPos = 0 );
221 
222 Data_Impl* Find( SfxTabDlgData_Impl& rArr, sal_uInt16 nId, sal_uInt16* pPos )
223 {
224     const sal_uInt16 nCount = rArr.Count();
225 
226     for ( sal_uInt16 i = 0; i < nCount; ++i )
227     {
228         Data_Impl* pObj = rArr[i];
229 
230         if ( pObj->nId == nId )
231         {
232             if ( pPos )
233                 *pPos = i;
234             return pObj;
235         }
236     }
237     return 0;
238 }
239 
240 #if !ENABLE_LAYOUT_SFX_TABDIALOG
241 
242 void SfxTabPage::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame)
243 {
244     if (pImpl)
245         pImpl->mxFrame = xFrame;
246 }
247 
248 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxTabPage::GetFrame()
249 {
250     if (pImpl)
251         return pImpl->mxFrame;
252     return ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >();
253 }
254 
255 SfxTabPage::SfxTabPage( Window *pParent,
256                         const ResId &rResId, const SfxItemSet &rAttrSet ) :
257 
258 /*  [Beschreibung]
259 
260     Konstruktor
261 */
262 
263     TabPage( pParent, rResId ),
264 
265     pSet                ( &rAttrSet ),
266     bHasExchangeSupport ( sal_False ),
267     pTabDlg             ( NULL ),
268     pImpl               ( new TabPageImpl )
269 
270 {
271 }
272 // -----------------------------------------------------------------------
273 SfxTabPage:: SfxTabPage( Window *pParent, WinBits nStyle, const SfxItemSet &rAttrSet ) :
274     TabPage(pParent, nStyle),
275     pSet                ( &rAttrSet ),
276     bHasExchangeSupport ( sal_False ),
277     pTabDlg             ( NULL ),
278     pImpl               ( new TabPageImpl )
279 {
280 }
281 // -----------------------------------------------------------------------
282 
283 SfxTabPage::~SfxTabPage()
284 
285 /*  [Beschreibung]
286 
287     Destruktor
288 */
289 
290 {
291 #if !ENABLE_LAYOUT
292     delete pImpl;
293 #endif /* ENABLE_LAYOUT */
294 }
295 
296 // -----------------------------------------------------------------------
297 
298 sal_Bool SfxTabPage::FillItemSet( SfxItemSet& rSet )
299 {
300     return pImpl->maItemConn.DoFillItemSet( rSet, GetItemSet() );
301 }
302 
303 // -----------------------------------------------------------------------
304 
305 void SfxTabPage::Reset( const SfxItemSet& rSet )
306 {
307     pImpl->maItemConn.DoApplyFlags( rSet );
308     pImpl->maItemConn.DoReset( rSet );
309 }
310 
311 // -----------------------------------------------------------------------
312 
313 void SfxTabPage::ActivatePage( const SfxItemSet& )
314 
315 /*  [Beschreibung]
316 
317     Defaultimplementierung der virtuellen ActivatePage-Methode
318     Diese wird gerufen, wenn eine Seite des Dialogs den Datenaustausch
319     zwischen Pages unterst"utzt.
320 
321     <SfxTabPage::DeactivatePage(SfxItemSet *)>
322 */
323 
324 {
325 }
326 
327 // -----------------------------------------------------------------------
328 
329 int SfxTabPage::DeactivatePage( SfxItemSet* )
330 
331 /*  [Beschreibung]
332 
333     Defaultimplementierung der virtuellen DeactivatePage-Methode
334     Diese wird vor dem Verlassen einer Seite durch den Sfx gerufen;
335     die Anwendung kann "uber den Returnwert steuern,
336     ob die Seite verlassen werden soll.
337     Falls die Seite "uber bHasExchangeSupport
338     anzeigt, da\s sie einen Datenaustausch zwischen Seiten
339     unterst"utzt, wird ein Pointer auf das Austausch-Set als
340     Parameter "ubergeben. Dieser nimmt die Daten f"ur den Austausch
341     entgegen; das Set steht anschlie\send als Parameter in
342     <SfxTabPage::ActivatePage(const SfxItemSet &)> zur Verf"ugung.
343 
344     [R"uckgabewert]
345 
346     LEAVE_PAGE; Verlassen der Seite erlauben
347 */
348 
349 {
350     return LEAVE_PAGE;
351 }
352 
353 // -----------------------------------------------------------------------
354 
355 void SfxTabPage::FillUserData()
356 
357 /*  [Beschreibung]
358 
359    virtuelle Methode, wird von der Basisklasse im Destruktor gerufen
360    um spezielle Informationen der TabPage in der Ini-Datei zu speichern.
361    Beim "Uberladen muss ein String zusammengestellt werden, der mit
362    <SetUserData()> dann weggeschrieben wird.
363 */
364 
365 {
366 }
367 
368 // -----------------------------------------------------------------------
369 
370 sal_Bool SfxTabPage::IsReadOnly() const
371 
372 /*  [Description]
373 
374 */
375 
376 {
377     return sal_False;
378 }
379 
380 // -----------------------------------------------------------------------
381 
382 const SfxPoolItem* SfxTabPage::GetItem( const SfxItemSet& rSet, sal_uInt16 nSlot, sal_Bool bDeep )
383 
384 /*  [Beschreibung]
385 
386     static Methode: hiermit wird der Code der TabPage-Implementierungen
387     vereinfacht.
388 
389 */
390 
391 {
392     const SfxItemPool* pPool = rSet.GetPool();
393     sal_uInt16 nWh = pPool->GetWhich( nSlot, bDeep );
394     const SfxPoolItem* pItem = 0;
395 #ifdef DEBUG
396     SfxItemState eState;
397     eState =
398 #endif
399             rSet.GetItemState( nWh, sal_True, &pItem );  // -Wall required??
400 
401     if ( !pItem && nWh != nSlot )
402         pItem = &pPool->GetDefaultItem( nWh );
403     return pItem;
404 }
405 
406 // -----------------------------------------------------------------------
407 
408 const SfxPoolItem* SfxTabPage::GetOldItem( const SfxItemSet& rSet,
409                                            sal_uInt16 nSlot, sal_Bool bDeep )
410 
411 /*  [Beschreibung]
412 
413     Diese Methode gibt f"ur Vergleiche den alten Wert eines
414     Attributs zur"uck.
415 */
416 
417 {
418     const SfxItemSet& rOldSet = GetItemSet();
419     sal_uInt16 nWh = GetWhich( nSlot, bDeep );
420     const SfxPoolItem* pItem = 0;
421 
422     if ( pImpl->mbStandard && rOldSet.GetParent() )
423         pItem = GetItem( *rOldSet.GetParent(), nSlot );
424     else if ( rSet.GetParent() &&
425               SFX_ITEM_DONTCARE == rSet.GetItemState( nWh ) )
426         pItem = GetItem( *rSet.GetParent(), nSlot );
427     else
428         pItem = GetItem( rOldSet, nSlot );
429     return pItem;
430 }
431 
432 // -----------------------------------------------------------------------
433 
434 const SfxPoolItem* SfxTabPage::GetExchangeItem( const SfxItemSet& rSet,
435                                                 sal_uInt16 nSlot )
436 
437 /*  [Beschreibung]
438 
439     Diese Methode gibt f"ur Vergleiche den alten Wert eines
440     Attributs zur"uck. Dabei wird ber"ucksichtigt, ob der Dialog
441     gerade mit OK beendet wurde.
442 */
443 
444 {
445     if ( pTabDlg && !pTabDlg->IsInOK() && pTabDlg->GetExampleSet() )
446         return GetItem( *pTabDlg->GetExampleSet(), nSlot );
447     else
448         return GetOldItem( rSet, nSlot );
449 }
450 
451 // add CHINA001  begin
452 void SfxTabPage::PageCreated( SfxAllItemSet /*aSet*/ )
453 {
454     DBG_ASSERT(0, "SfxTabPage::PageCreated should not be called");
455 }//CHINA001
456 // add CHINA001 end
457 
458 // -----------------------------------------------------------------------
459 
460 void SfxTabPage::AddItemConnection( sfx::ItemConnectionBase* pConnection )
461 {
462     pImpl->maItemConn.AddConnection( pConnection );
463 }
464 
465 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
466 
467 #if ENABLE_LAYOUT_SFX_TABDIALOG
468 #undef ResId
469 #define ResId(id, foo) #id
470 #undef TabDialog
471 #define TabDialog(parent, res_id) Dialog (parent, "tab-dialog.xml", "tab-dialog")
472 
473 #define aOKBtn(this) aOKBtn (this, "BTN_OK")
474 #undef PushButton
475 #define PushButton(this) layout::PushButton (this, "BTN_USER")
476 #define aCancelBtn(this) aCancelBtn (this, "BTN_CANCEL")
477 #define aHelpBtn(this) aHelpBtn (this, "BTN_HELP")
478 #define aResetBtn(this) aResetBtn (this, "BTN_RESET")
479 #define aBaseFmtBtn(this) aBaseFmtBtn (this, "BTN_BASEFMT")
480 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
481 
482 #define INI_LIST(ItemSetPtr) \
483     aTabCtrl    ( this, ResId(ID_TABCONTROL,*rResId.GetResMgr() ) ),\
484     aOKBtn      ( this ),\
485     pUserBtn    ( pUserButtonText? new PushButton(this): 0 ),\
486     aCancelBtn  ( this ),\
487     aHelpBtn    ( this ),\
488     aResetBtn   ( this ),\
489     aBaseFmtBtn ( this ),\
490     pSet        ( ItemSetPtr ),\
491     pOutSet     ( 0 ),\
492     pImpl       ( new TabDlg_Impl( (sal_uInt8)aTabCtrl.GetPageCount() ) ), \
493     pRanges     ( 0 ), \
494     nResId      ( rResId.GetId() ), \
495     nAppPageId  ( USHRT_MAX ), \
496     bItemsReset ( sal_False ),\
497     bFmt        ( bEditFmt ),\
498     pExampleSet ( 0 )
499 
500 // -----------------------------------------------------------------------
501 
502 SfxTabDialog::SfxTabDialog
503 
504 /*  [Beschreibung]
505 
506     Konstruktor
507 */
508 
509 (
510     SfxViewFrame* pViewFrame,       // Frame, zu dem der Dialog geh"ort
511     Window* pParent,                // Parent-Fenster
512     const ResId& rResId,            // ResourceId
513     const SfxItemSet* pItemSet,     // Itemset mit den Daten;
514                                     // kann NULL sein, wenn Pages onDemand
515     sal_Bool bEditFmt,      // Flag: es werden Vorlagen bearbeitet
516                         // wenn ja -> zus"atzlicher Button f"ur Standard
517     const String* pUserButtonText   // Text fuer BenutzerButton;
518                                     // wenn != 0, wird der UserButton erzeugt
519 ) :
520     TabDialog( pParent, rResId ),
521     pFrame( pViewFrame ),
522     INI_LIST(pItemSet)
523 {
524     Init_Impl( bFmt, pUserButtonText );
525 }
526 
527 // -----------------------------------------------------------------------
528 
529 SfxTabDialog::SfxTabDialog
530 
531 /*  [Beschreibung]
532 
533     Konstruktor, tempor"ar ohne Frame
534 */
535 
536 (
537     Window* pParent,                // Parent-Fenster
538     const ResId& rResId,            // ResourceId
539     const SfxItemSet* pItemSet,     // Itemset mit den Daten; kann NULL sein,
540                                     // wenn Pages onDemand
541     sal_Bool bEditFmt,      // Flag: es werden Vorlagen bearbeitet
542                         // wenn ja -> zus"atzlicher Button f"ur Standard
543     const String* pUserButtonText   // Text f"ur BenutzerButton;
544                                     // wenn != 0, wird der UserButton erzeugt
545 ) :
546     TabDialog( pParent, rResId ),
547     pFrame( 0 ),
548     INI_LIST(pItemSet)
549 {
550     Init_Impl( bFmt, pUserButtonText );
551     DBG_WARNING( "bitte den Ctor mit ViewFrame verwenden" );
552 }
553 
554 SfxTabDialog::SfxTabDialog
555 
556 /*  [Beschreibung]
557 
558     Konstruktor, tempor"ar ohne Frame
559 */
560 
561 (
562     Window* pParent,                // Parent-Fenster
563     const ResId& rResId,            // ResourceId
564     sal_uInt16 nSetId,
565     SfxBindings& rBindings,
566     sal_Bool bEditFmt,      // Flag: es werden Vorlagen bearbeitet
567                         // wenn ja -> zus"atzlicher Button f"ur Standard
568     const String* pUserButtonText   // Text f"ur BenutzerButton;
569                                     // wenn != 0, wird der UserButton erzeugt
570 ) :
571     TabDialog( pParent, rResId ),
572     pFrame( 0 ),
573     INI_LIST(NULL)
574 {
575     rBindings.ENTERREGISTRATIONS();
576     pImpl->pController = new SfxTabDialogController( nSetId, rBindings, this );
577     rBindings.LEAVEREGISTRATIONS();
578 
579     EnableApplyButton( sal_True );
580     SetApplyHandler( LINK( pImpl->pController, SfxTabDialogController, Execute_Impl ) );
581 
582     rBindings.Invalidate( nSetId );
583     rBindings.Update( nSetId );
584     DBG_ASSERT( pSet, "No ItemSet!" );
585 
586     Init_Impl( bFmt, pUserButtonText );
587 }
588 
589 // -----------------------------------------------------------------------
590 
591 #if ENABLE_LAYOUT_SFX_TABDIALOG
592 #undef ResId
593 #undef TabDialog
594 #undef aOKBtn
595 #undef PushButton
596 #undef aCancelBtn
597 #undef aHelpBtn
598 #undef aResetBtn
599 #undef aBaseFmtBtn
600 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
601 
602 SfxTabDialog::~SfxTabDialog()
603 {
604     // save settings (screen position and current page)
605     SvtViewOptions aDlgOpt( E_TABDIALOG, String::CreateFromInt32( nResId ) );
606 #if !ENABLE_LAYOUT_SFX_TABDIALOG
607     aDlgOpt.SetWindowState( OUString::createFromAscii( GetWindowState( WINDOWSTATE_MASK_POS ).GetBuffer() ) );
608 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
609     aDlgOpt.SetPageID( aTabCtrl.GetCurPageId() );
610 
611     const sal_uInt16 nCount = pImpl->pData->Count();
612     for ( sal_uInt16 i = 0; i < nCount; ++i )
613     {
614         Data_Impl* pDataObject = pImpl->pData->GetObject(i);
615 
616         if ( pDataObject->pTabPage )
617         {
618             // save settings of all pages (user data)
619             pDataObject->pTabPage->FillUserData();
620             String aPageData( pDataObject->pTabPage->GetUserData() );
621             if ( aPageData.Len() )
622             {
623                 // save settings of all pages (user data)
624                 SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) );
625                 aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) );
626             }
627 
628             if ( pDataObject->bOnDemand )
629                 delete (SfxItemSet*)&pDataObject->pTabPage->GetItemSet();
630             delete pDataObject->pTabPage;
631         }
632         delete pDataObject;
633     }
634 
635     delete pImpl->pController;
636     delete pImpl->pApplyButton;
637     delete pImpl->pData;
638     delete pImpl;
639     delete pUserBtn;
640     delete pOutSet;
641     delete pExampleSet;
642     delete [] pRanges;
643 }
644 
645 // -----------------------------------------------------------------------
646 
647 void SfxTabDialog::Init_Impl( sal_Bool bFmtFlag, const String* pUserButtonText )
648 
649 /*  [Beschreibung]
650 
651     interne Initialisierung des Dialogs
652 */
653 
654 {
655     aOKBtn.SetClickHdl( LINK( this, SfxTabDialog, OkHdl ) );
656     aResetBtn.SetClickHdl( LINK( this, SfxTabDialog, ResetHdl ) );
657     aResetBtn.SetText( String( SfxResId( STR_RESET ) ) );
658     aTabCtrl.SetActivatePageHdl(
659             LINK( this, SfxTabDialog, ActivatePageHdl ) );
660     aTabCtrl.SetDeactivatePageHdl(
661             LINK( this, SfxTabDialog, DeactivatePageHdl ) );
662     aTabCtrl.Show();
663     aOKBtn.Show();
664     aCancelBtn.Show();
665     aHelpBtn.Show();
666     aResetBtn.Show();
667     aResetBtn.SetHelpId( HID_TABDLG_RESET_BTN );
668 
669     if ( pUserBtn )
670     {
671         pUserBtn->SetText( *pUserButtonText );
672         pUserBtn->SetClickHdl( LINK( this, SfxTabDialog, UserHdl ) );
673         pUserBtn->Show();
674     }
675 
676     /* TODO: Check what is up with bFmt/bFmtFlag. Comment below suggests a
677              different behavior than implemented!! */
678     if ( bFmtFlag )
679     {
680         String aStd( SfxResId( STR_STANDARD_SHORTCUT ) );
681         aBaseFmtBtn.SetText( aStd );
682         aBaseFmtBtn.SetClickHdl( LINK( this, SfxTabDialog, BaseFmtHdl ) );
683         aBaseFmtBtn.SetHelpId( HID_TABDLG_STANDARD_BTN );
684 
685         // bFmt = tempor"ares Flag im Ctor() "ubergeben,
686         // wenn bFmt == 2, dann auch sal_True,
687         // zus"atzlich Ausblendung vom StandardButton,
688         // nach der Initialisierung wieder auf sal_True setzen
689         if ( bFmtFlag != 2 )
690             aBaseFmtBtn.Show();
691         else
692             bFmtFlag = sal_True;
693     }
694 
695     if ( pSet )
696     {
697         pExampleSet = new SfxItemSet( *pSet );
698         pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() );
699     }
700 
701     aOKBtn.SetAccessibleRelationMemberOf( &aOKBtn );
702     aCancelBtn.SetAccessibleRelationMemberOf( &aCancelBtn );
703     aHelpBtn.SetAccessibleRelationMemberOf( &aHelpBtn );
704     aResetBtn.SetAccessibleRelationMemberOf( &aResetBtn );
705 }
706 
707 // -----------------------------------------------------------------------
708 
709 void SfxTabDialog::RemoveResetButton()
710 {
711     aResetBtn.Hide();
712     pImpl->bHideResetBtn = sal_True;
713 }
714 
715 // -----------------------------------------------------------------------
716 
717 #if ENABLE_LAYOUT_SFX_TABDIALOG
718 #undef TabDialog
719 #define TabDialog Dialog
720 #endif /* ENABLE_LAYOUT_SFX_TABDIALOG */
721 
722 short SfxTabDialog::Execute()
723 {
724     if ( !aTabCtrl.GetPageCount() )
725         return RET_CANCEL;
726     Start_Impl();
727     return TabDialog::Execute();
728 }
729 
730 // -----------------------------------------------------------------------
731 
732 void SfxTabDialog::StartExecuteModal( const Link& rEndDialogHdl )
733 {
734 #if !ENABLE_LAYOUT_SFX_TABDIALOG
735     if ( !aTabCtrl.GetPageCount() )
736         return;
737     Start_Impl();
738     TabDialog::StartExecuteModal( rEndDialogHdl );
739 #else
740     rEndDialogHdl.IsSet();
741 #endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */
742 }
743 
744 // -----------------------------------------------------------------------
745 
746 void SfxTabDialog::Start( sal_Bool bShow )
747 {
748     aCancelBtn.SetClickHdl( LINK( this, SfxTabDialog, CancelHdl ) );
749     pImpl->bModal = sal_False;
750     Start_Impl();
751 
752     if ( bShow )
753         Show();
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