xref: /trunk/main/sfx2/source/dialog/basedlgs.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 ---------------------------------------------------------------
32 
33 #include <stdlib.h>
34 #include <vcl/fixed.hxx>
35 #include <vcl/help.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <svl/eitem.hxx>
38 #include <unotools/viewoptions.hxx>
39 #include <svtools/fixedhyper.hxx>
40 #include <svtools/controldims.hrc>
41 
42 #include <sfx2/basedlgs.hxx>
43 #include <sfx2/viewfrm.hxx>
44 #include <sfx2/tabdlg.hxx>
45 #include <sfx2/app.hxx>
46 #include <sfx2/bindings.hxx>
47 #include <sfx2/dispatch.hxx>
48 #include <sfx2/childwin.hxx>
49 #include <sfx2/viewsh.hxx>
50 #include "sfx2/sfxhelp.hxx"
51 #include "workwin.hxx"
52 #include "sfx2/sfxresid.hxx"
53 #include "dialog.hrc"
54 
55 using namespace ::com::sun::star::uno;
56 using namespace ::rtl;
57 
58 #define USERITEM_NAME OUString::createFromAscii( "UserItem" )
59 
60 class SfxModelessDialog_Impl : public SfxListener
61 {
62 public:
63     ByteString      aWinState;
64     SfxChildWindow* pMgr;
65     sal_Bool            bConstructed;
66     void            Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
67 
68     Timer           aMoveTimer;
69 };
70 
71 void SfxModelessDialog_Impl::Notify( SfxBroadcaster&, const SfxHint& rHint )
72 {
73     if ( rHint.IsA(TYPE(SfxSimpleHint)) )
74     {
75         switch( ( (SfxSimpleHint&) rHint ).GetId() )
76         {
77             case SFX_HINT_DYING:
78                 pMgr->Destroy();
79                 break;
80         }
81     }
82 }
83 
84 class SfxFloatingWindow_Impl : public SfxListener
85 {
86 public:
87     ByteString      aWinState;
88     SfxChildWindow* pMgr;
89     sal_Bool            bConstructed;
90     Timer           aMoveTimer;
91 
92     void            Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
93 };
94 
95 void SfxFloatingWindow_Impl::Notify( SfxBroadcaster&, const SfxHint& rHint )
96 {
97     if ( rHint.IsA(TYPE(SfxSimpleHint)) )
98     {
99         switch( ( (SfxSimpleHint&) rHint ).GetId() )
100         {
101             case SFX_HINT_DYING:
102                 pMgr->Destroy();
103                 break;
104         }
105     }
106 }
107 
108 // class SfxModalDefParentHelper -----------------------------------------
109 
110 SfxModalDefParentHelper::SfxModalDefParentHelper( Window *pWindow)
111 {
112     pOld = Application::GetDefDialogParent();
113     Application::SetDefDialogParent( pWindow );
114 }
115 
116 // -----------------------------------------------------------------------
117 
118 SfxModalDefParentHelper::~SfxModalDefParentHelper()
119 {
120     Application::SetDefDialogParent( pOld );
121 }
122 
123 // -----------------------------------------------------------------------
124 
125 void SfxModalDialog::SetDialogData_Impl()
126 {
127     // save settings (position and user data)
128     SvtViewOptions aDlgOpt( E_DIALOG, String::CreateFromInt32( nUniqId ) );
129     aDlgOpt.SetWindowState(
130         OUString::createFromAscii( GetWindowState( WINDOWSTATE_MASK_POS ).GetBuffer() ) );
131     if ( aExtraData.Len() )
132         aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aExtraData ) ) );
133 }
134 
135 // -----------------------------------------------------------------------
136 
137 void SfxModalDialog::GetDialogData_Impl()
138 
139 /*      [Beschreibung]
140 
141     Hilfsfunktion; liest die Dialogposition aus der Ini-Datei
142     und setzt diese am "ubergebenen Window.
143 */
144 
145 {
146     SvtViewOptions aDlgOpt( E_DIALOG, String::CreateFromInt32( nUniqId ) );
147     if ( aDlgOpt.Exists() )
148     {
149         // load settings
150         SetWindowState( ByteString( aDlgOpt.GetWindowState().getStr(), RTL_TEXTENCODING_ASCII_US ) );
151         Any aUserItem = aDlgOpt.GetUserItem( USERITEM_NAME );
152         OUString aTemp;
153         if ( aUserItem >>= aTemp )
154             aExtraData = String( aTemp );
155     }
156 }
157 
158 // -----------------------------------------------------------------------
159 
160 void SfxModalDialog::init()
161 {
162     GetDialogData_Impl();
163 }
164 
165 // -----------------------------------------------------------------------
166 
167 SfxModalDialog::SfxModalDialog(Window* pParent, const ResId &rResId )
168 
169 /*      [Beschreibung]
170 
171     Konstruktor der allgemeinen Basisklasse f"ur modale Dialoge;
172     ResId wird als ID im ini-file verwendet.
173     Die dort gespeicherte Position wird gesetzt.
174 */
175 
176 :   ModalDialog(pParent, rResId),
177     nUniqId(rResId.GetId()),
178     pInputSet(0),
179     pOutputSet(0)
180 {
181     init();
182 }
183 
184 // -----------------------------------------------------------------------
185 
186 SfxModalDialog::SfxModalDialog(Window* pParent,
187                                sal_uInt32 nUniqueId,
188                                WinBits nWinStyle) :
189 /*      [Beschreibung]
190 
191     Konstruktor der allgemeinen Basisklasse f"ur modale Dialoge;
192     ID f"ur das ini-file wird explizit "ubergeben.
193     Die dort gespeicherte Position wird gesetzt.
194 */
195 
196     ModalDialog(pParent, nWinStyle),
197     nUniqId(nUniqueId),
198     pInputSet(0),
199     pOutputSet(0)
200 {
201     init();
202 }
203 
204 // -----------------------------------------------------------------------
205 
206 SfxModalDialog::~SfxModalDialog()
207 
208 /*      [Beschreibung]
209 
210     Dtor; schreibt Dialogposition in das ini-file
211 */
212 
213 {
214     SetDialogData_Impl();
215     delete pOutputSet;
216 }
217 
218 void SfxModalDialog::CreateOutputItemSet( SfxItemPool& rPool )
219 {
220     DBG_ASSERT( !pOutputSet, "Double creation of OutputSet!" );
221     if (!pOutputSet)
222         pOutputSet = new SfxAllItemSet( rPool );
223 }
224 
225 // -----------------------------------------------------------------------
226 
227 void SfxModalDialog::CreateOutputItemSet( const SfxItemSet& rSet )
228 {
229     DBG_ASSERT( !pOutputSet, "Double creation of OutputSet!" );
230     if (!pOutputSet)
231     {
232         pOutputSet = new SfxItemSet( rSet );
233         pOutputSet->ClearItem();
234     }
235 }
236 
237 //-------------------------------------------------------------------------
238 void SfxModelessDialog::StateChanged( StateChangedType nStateChange )
239 {
240     if ( nStateChange == STATE_CHANGE_INITSHOW )
241     {
242         if ( pImp->aWinState.Len() )
243         {
244             SetWindowState( pImp->aWinState );
245         }
246         else
247         {
248             Point aPos = GetPosPixel();
249             if ( !aPos.X() )
250             {
251                 aSize = GetSizePixel();
252 
253                 Size aParentSize = GetParent()->GetOutputSizePixel();
254                 Size aDlgSize = GetSizePixel();
255                 aPos.X() += ( aParentSize.Width() - aDlgSize.Width() ) / 2;
256                 aPos.Y() += ( aParentSize.Height() - aDlgSize.Height() ) / 2;
257 
258                 Point aPoint;
259                 Rectangle aRect = GetDesktopRectPixel();
260                 aPoint.X() = aRect.Right() - aDlgSize.Width();
261                 aPoint.Y() = aRect.Bottom() - aDlgSize.Height();
262 
263                 aPoint = OutputToScreenPixel( aPoint );
264 
265                 if ( aPos.X() > aPoint.X() )
266                     aPos.X() = aPoint.X() ;
267                 if ( aPos.Y() > aPoint.Y() )
268                     aPos.Y() = aPoint.Y();
269 
270                 if ( aPos.X() < 0 ) aPos.X() = 0;
271                 if ( aPos.Y() < 0 ) aPos.Y() = 0;
272 
273                 SetPosPixel( aPos );
274             }
275         }
276 
277         pImp->bConstructed = sal_True;
278     }
279 
280     ModelessDialog::StateChanged( nStateChange );
281 }
282 
283 void SfxModelessDialog::Initialize(SfxChildWinInfo *pInfo)
284 
285 /*  [Beschreibung]
286 
287     Initialisierung der Klasse SfxModelessDialog "uber ein SfxChildWinInfo.
288     Die Initialisierung erfolgt erst in einem 2.Schritt
289     nach dem ctor und sollte vom ctor der abgeleiteten Klasse
290     oder von dem des SfxChildWindows aufgerufen werden.
291 */
292 
293 {
294     pImp->aWinState = pInfo->aWinState;
295 }
296 
297 void SfxModelessDialog::Resize()
298 
299 /*  [Beschreibung]
300 
301     Diese virtuelle Methode der Klasse FloatingWindow merkt sich ggf. eine
302     ver"anderte Gr"o\se.
303     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
304     auch SfxFloatingWindow::Resize() gerufen werden.
305 */
306 
307 {
308     ModelessDialog::Resize();
309     if ( pImp->bConstructed && pImp->pMgr )
310     {
311         // start timer for saving window status information
312         pImp->aMoveTimer.Start();
313     }
314 }
315 
316 void SfxModelessDialog::Move()
317 {
318     ModelessDialog::Move();
319     if ( pImp->bConstructed && pImp->pMgr && IsReallyVisible() )
320     {
321         // start timer for saving window status information
322         pImp->aMoveTimer.Start();
323     }
324 }
325 
326 /*
327     Implements a timer event that is triggered by a move or resize of the window
328     This will save config information to Views.xcu with a small delay
329 */
330 IMPL_LINK( SfxModelessDialog, TimerHdl, Timer*, EMPTYARG)
331 {
332     pImp->aMoveTimer.Stop();
333     if ( pImp->bConstructed && pImp->pMgr )
334     {
335         if ( !IsRollUp() )
336             aSize = GetSizePixel();
337         sal_uIntPtr nMask = WINDOWSTATE_MASK_POS | WINDOWSTATE_MASK_STATE;
338         if ( GetStyle() & WB_SIZEABLE )
339             nMask |= ( WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT );
340         pImp->aWinState = GetWindowState( nMask );
341         GetBindings().GetWorkWindow_Impl()->ConfigChild_Impl( SFX_CHILDWIN_DOCKINGWINDOW, SFX_ALIGNDOCKINGWINDOW, pImp->pMgr->GetType() );
342     }
343     return 0;
344 }
345 
346 // -----------------------------------------------------------------------
347 
348 SfxModelessDialog::SfxModelessDialog( SfxBindings *pBindinx,
349                         SfxChildWindow *pCW,
350                         Window* pParent, WinBits nWinBits ) :
351     ModelessDialog (pParent, nWinBits),
352     pBindings(pBindinx),
353     pImp( new SfxModelessDialog_Impl )
354 {
355     pImp->pMgr = pCW;
356     pImp->bConstructed = sal_False;
357     SetUniqueId( GetHelpId() );
358     SetHelpId("");
359     if ( pBindinx )
360         pImp->StartListening( *pBindinx );
361     pImp->aMoveTimer.SetTimeout(50);
362     pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxModelessDialog,TimerHdl));
363 }
364 
365 // -----------------------------------------------------------------------
366 
367 SfxModelessDialog::SfxModelessDialog( SfxBindings *pBindinx,
368                         SfxChildWindow *pCW, Window *pParent,
369                         const ResId& rResId ) :
370     ModelessDialog(pParent, rResId),
371     pBindings(pBindinx),
372     pImp( new SfxModelessDialog_Impl )
373 {
374     pImp->pMgr = pCW;
375     pImp->bConstructed = sal_False;
376     SetUniqueId( GetHelpId() );
377     SetHelpId("");
378     if ( pBindinx )
379         pImp->StartListening( *pBindinx );
380     pImp->aMoveTimer.SetTimeout(50);
381     pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxModelessDialog,TimerHdl));
382 }
383 
384 // -----------------------------------------------------------------------
385 
386 long SfxModelessDialog::Notify( NotifyEvent& rEvt )
387 
388 /*      [Beschreibung]
389 
390     Wenn ein ModelessDialog aktiviert wird, wird sein ViewFrame aktiviert.
391     Notwendig ist das bei PlugInFrames.
392 */
393 
394 {
395     if ( rEvt.GetType() == EVENT_GETFOCUS )
396     {
397         pBindings->SetActiveFrame( pImp->pMgr->GetFrame() );
398         pImp->pMgr->Activate_Impl();
399         Window* pWindow = rEvt.GetWindow();
400         rtl::OString sHelpId;
401         while ( !sHelpId.getLength() && pWindow )
402         {
403             sHelpId = pWindow->GetHelpId();
404             pWindow = pWindow->GetParent();
405         }
406 
407         if ( sHelpId.getLength() )
408             SfxHelp::OpenHelpAgent( &pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame(), sHelpId );
409     }
410     else if ( rEvt.GetType() == EVENT_LOSEFOCUS && !HasChildPathFocus() )
411     {
412         pBindings->SetActiveFrame( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > () );
413         pImp->pMgr->Deactivate_Impl();
414     }
415     else if( rEvt.GetType() == EVENT_KEYINPUT )
416     {
417         // KeyInput zuerst f"ur Dialogfunktionen zulassen ( TAB etc. )
418         if ( !ModelessDialog::Notify( rEvt ) && SfxViewShell::Current() )
419             // dann auch global g"ultige Acceleratoren verwenden
420             return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt.GetKeyEvent() );
421         return sal_True;
422     }
423 
424     return ModelessDialog::Notify( rEvt );
425 }
426 
427 // -----------------------------------------------------------------------
428 
429 SfxModelessDialog::~SfxModelessDialog()
430 
431 /*      [Beschreibung]
432 
433     Dtor
434 */
435 
436 {
437     if ( pImp->pMgr->GetFrame().is() && pImp->pMgr->GetFrame() == pBindings->GetActiveFrame() )
438         pBindings->SetActiveFrame( NULL );
439     delete pImp;
440 }
441 
442 //-------------------------------------------------------------------------
443 
444 sal_Bool SfxModelessDialog::Close()
445 
446 /*      [Beschreibung]
447 
448     Das Fenster wird geschlossen, indem das ChildWindow durch Ausf"uhren des
449     ChildWindow-Slots zerst"ort wird.
450     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
451     danach SfxModelessDialogWindow::Close() gerufen werden, wenn nicht das
452     Close() mit "return sal_False" abgebrochen wird.
453 
454 */
455 
456 {
457     // Execute mit Parametern, da Toggle von einigen ChildWindows ignoriert
458     // werden kann
459     SfxBoolItem aValue( pImp->pMgr->GetType(), sal_False);
460     pBindings->GetDispatcher_Impl()->Execute(
461         pImp->pMgr->GetType(),
462         SFX_CALLMODE_RECORD|SFX_CALLMODE_SYNCHRON, &aValue, 0L );
463     return sal_True;
464 }
465 
466 //-------------------------------------------------------------------------
467 
468 void SfxModelessDialog::FillInfo(SfxChildWinInfo& rInfo) const
469 
470 /*  [Beschreibung]
471 
472     F"ullt ein SfxChildWinInfo mit f"ur SfxModelessDialof spezifischen Daten,
473     damit sie in die INI-Datei geschrieben werden koennen.
474     Es wird angenommen, da\s rInfo alle anderen evt. relevanten Daten in
475     der ChildWindow-Klasse erh"alt.
476     ModelessDialogs haben keine spezifischen Informationen, so dass die
477     Basisimplementierung nichts tut und daher nicht gerufen werden mu\s.
478 */
479 
480 {
481     rInfo.aSize  = aSize;
482     if ( IsRollUp() )
483         rInfo.nFlags |= SFX_CHILDWIN_ZOOMIN;
484 }
485 
486 // -----------------------------------------------------------------------
487 
488 long SfxFloatingWindow::Notify( NotifyEvent& rEvt )
489 
490 /*      [Beschreibung]
491 
492     Wenn ein ModelessDialog aktiviert wird, wird sein ViewFrame aktiviert.
493     Notwendig ist das bei PlugInFrames.
494 */
495 
496 {
497     if ( rEvt.GetType() == EVENT_GETFOCUS )
498     {
499         pBindings->SetActiveFrame( pImp->pMgr->GetFrame() );
500         pImp->pMgr->Activate_Impl();
501         Window* pWindow = rEvt.GetWindow();
502         rtl::OString sHelpId;
503         while ( !sHelpId.getLength() && pWindow )
504         {
505             sHelpId = pWindow->GetHelpId();
506             pWindow = pWindow->GetParent();
507         }
508 
509         if ( sHelpId.getLength() )
510             SfxHelp::OpenHelpAgent( &pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame(), sHelpId );
511     }
512     else if ( rEvt.GetType() == EVENT_LOSEFOCUS )
513     {
514         if ( !HasChildPathFocus() )
515         {
516             pBindings->SetActiveFrame( NULL );
517             pImp->pMgr->Deactivate_Impl();
518         }
519     }
520     else if( rEvt.GetType() == EVENT_KEYINPUT )
521     {
522         // KeyInput zuerst f"ur Dialogfunktionen zulassen
523         if ( !FloatingWindow::Notify( rEvt ) && SfxViewShell::Current() )
524             // dann auch global g"ultige Acceleratoren verwenden
525             return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt.GetKeyEvent() );
526         return sal_True;
527     }
528 
529     return FloatingWindow::Notify( rEvt );
530 }
531 
532 // -----------------------------------------------------------------------
533 
534 SfxFloatingWindow::SfxFloatingWindow( SfxBindings *pBindinx,
535                         SfxChildWindow *pCW,
536                         Window* pParent, WinBits nWinBits) :
537     FloatingWindow (pParent, nWinBits),
538     pBindings(pBindinx),
539     pImp( new SfxFloatingWindow_Impl )
540 {
541     pImp->pMgr = pCW;
542     pImp->bConstructed = sal_False;
543     SetUniqueId( GetHelpId() );
544     SetHelpId("");
545     if ( pBindinx )
546         pImp->StartListening( *pBindinx );
547     pImp->aMoveTimer.SetTimeout(50);
548     pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxFloatingWindow,TimerHdl));
549 }
550 
551 // -----------------------------------------------------------------------
552 
553 SfxFloatingWindow::SfxFloatingWindow( SfxBindings *pBindinx,
554                         SfxChildWindow *pCW,
555                         Window* pParent,
556                         const ResId& rResId) :
557     FloatingWindow(pParent, rResId),
558     pBindings(pBindinx),
559     pImp( new SfxFloatingWindow_Impl )
560 {
561     pImp->pMgr = pCW;
562     pImp->bConstructed = sal_False;
563     SetUniqueId( GetHelpId() );
564     SetHelpId("");
565     if ( pBindinx )
566         pImp->StartListening( *pBindinx );
567     pImp->aMoveTimer.SetTimeout(50);
568     pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxFloatingWindow,TimerHdl));
569 }
570 
571 //-------------------------------------------------------------------------
572 
573 sal_Bool SfxFloatingWindow::Close()
574 
575 /*      [Beschreibung]
576 
577     Das Fenster wird geschlossen, indem das ChildWindow durch Ausf"uhren des
578     ChildWindow-Slots zerst"ort wird.
579     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
580     danach SfxFloatingWindow::Close() gerufen werden, wenn nicht das Close()
581     mit "return sal_False" abgebrochen wird.
582 
583 */
584 
585 {
586     // Execute mit Parametern, da Toggle von einigen ChildWindows ignoriert
587     // werden kann
588     SfxBoolItem aValue( pImp->pMgr->GetType(), sal_False);
589     pBindings->GetDispatcher_Impl()->Execute(
590             pImp->pMgr->GetType(),
591             SFX_CALLMODE_RECORD|SFX_CALLMODE_SYNCHRON, &aValue, 0L );
592     return sal_True;
593 }
594 
595 // -----------------------------------------------------------------------
596 
597 SfxFloatingWindow::~SfxFloatingWindow()
598 
599 /*      [Beschreibung]
600 
601     Dtor
602 */
603 
604 {
605     if ( pImp->pMgr->GetFrame() == pBindings->GetActiveFrame() )
606         pBindings->SetActiveFrame( NULL );
607     delete pImp;
608 }
609 
610 //-------------------------------------------------------------------------
611 
612 void SfxFloatingWindow::Resize()
613 
614 /*  [Beschreibung]
615 
616     Diese virtuelle Methode der Klasse FloatingWindow merkt sich ggf. eine
617     ver"anderte Gr"o\se.
618     Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s
619     auch SfxFloatingWindow::Resize() gerufen werden.
620 */
621 
622 {
623     FloatingWindow::Resize();
624     if ( pImp->bConstructed && pImp->pMgr )
625     {
626         // start timer for saving window status information
627         pImp->aMoveTimer.Start();
628     }
629 }
630 
631 void SfxFloatingWindow::Move()
632 {
633     FloatingWindow::Move();
634     if ( pImp->bConstructed && pImp->pMgr )
635     {
636         // start timer for saving window status information
637         pImp->aMoveTimer.Start();
638     }
639 }
640 
641 /*
642     Implements a timer event that is triggered by a move or resize of the window
643     This will save config information to Views.xcu with a small delay
644 */
645 IMPL_LINK( SfxFloatingWindow, TimerHdl, Timer*, EMPTYARG)
646 {
647     pImp->aMoveTimer.Stop();
648     if ( pImp->bConstructed && pImp->pMgr )
649     {
650         if ( !IsRollUp() )
651             aSize = GetSizePixel();
652         sal_uIntPtr nMask = WINDOWSTATE_MASK_POS | WINDOWSTATE_MASK_STATE;
653         if ( GetStyle() & WB_SIZEABLE )
654             nMask |= ( WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT );
655         pImp->aWinState = GetWindowState( nMask );
656         GetBindings().GetWorkWindow_Impl()->ConfigChild_Impl( SFX_CHILDWIN_DOCKINGWINDOW, SFX_ALIGNDOCKINGWINDOW, pImp->pMgr->GetType() );
657     }
658     return 0;
659 }
660 
661 //-------------------------------------------------------------------------
662 void SfxFloatingWindow::StateChanged( StateChangedType nStateChange )
663 {
664     if ( nStateChange == STATE_CHANGE_INITSHOW )
665     {
666         // FloatingWindows are not centered by default
667         if ( pImp->aWinState.Len() )
668             SetWindowState( pImp->aWinState );
669         pImp->bConstructed = sal_True;
670     }
671 
672     FloatingWindow::StateChanged( nStateChange );
673 }
674 
675 
676 void SfxFloatingWindow::Initialize(SfxChildWinInfo *pInfo)
677 
678 /*  [Beschreibung]
679 
680     Initialisierung der Klasse SfxFloatingWindow "uber ein SfxChildWinInfo.
681     Die Initialisierung erfolgt erst in einem 2.Schritt
682     nach dem ctor und sollte vom ctor der abgeleiteten Klasse
683     oder von dem des SfxChildWindows aufgerufen werden.
684 */
685 {
686     pImp->aWinState = pInfo->aWinState;
687 }
688 
689 //-------------------------------------------------------------------------
690 
691 void SfxFloatingWindow::FillInfo(SfxChildWinInfo& rInfo) const
692 
693 /*  [Beschreibung]
694 
695     F"ullt ein SfxChildWinInfo mit f"ur SfxFloatingWindow spezifischen Daten,
696     damit sie in die INI-Datei geschrieben werden koennen.
697     Es wird angenommen, da\s rInfo alle anderen evt. relevanten Daten in
698     der ChildWindow-Klasse erh"alt.
699     Eingetragen werden hier gemerkte Gr"o\se und das ZoomIn-Flag.
700     Wird diese Methode "uberschrieben, mu\s zuerst die Basisimplementierung
701     gerufen werden.
702 */
703 
704 {
705     rInfo.aSize  = aSize;
706     if ( IsRollUp() )
707         rInfo.nFlags |= SFX_CHILDWIN_ZOOMIN;
708 }
709 
710 // SfxSingleTabDialog ----------------------------------------------------
711 
712 IMPL_LINK( SfxSingleTabDialog, OKHdl_Impl, Button *, EMPTYARG )
713 
714 /*      [Beschreibung]
715 
716     Ok_Handler; f"ur die gesetzte Page wird FillItemSet() gerufen.
717 */
718 
719 {
720     if ( !GetInputItemSet() )
721     {
722         // TabPage without ItemSet
723         EndDialog( RET_OK );
724         return 1;
725     }
726 
727     if ( !GetOutputItemSet() )
728     {
729         CreateOutputItemSet( *GetInputItemSet() );
730     }
731     sal_Bool bModified = sal_False;
732 
733     if ( pImpl->m_pSfxPage->HasExchangeSupport() )
734     {
735         int nRet = pImpl->m_pSfxPage->DeactivatePage( GetOutputSetImpl() );
736         if ( nRet != SfxTabPage::LEAVE_PAGE )
737             return 0;
738         else
739             bModified = ( GetOutputItemSet()->Count() > 0 );
740     }
741     else
742         bModified = pImpl->m_pSfxPage->FillItemSet( *GetOutputSetImpl() );
743 
744     if ( bModified )
745     {
746         // auch noch schnell User-Daten im IniManager abspeichern
747         pImpl->m_pSfxPage->FillUserData();
748         String sData( pImpl->m_pSfxPage->GetUserData() );
749         SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( GetUniqId() ) );
750         aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( sData ) ) );
751         EndDialog( RET_OK );
752     }
753     else
754         EndDialog( RET_CANCEL );
755     return 0;
756 }
757 
758 // -----------------------------------------------------------------------
759 
760 SfxSingleTabDialog::SfxSingleTabDialog
761 (
762     Window *pParent,
763     const SfxItemSet& rSet,
764     sal_uInt16 nUniqueId
765 ) :
766 
767 /*      [Beschreibung]
768 
769     Konstruktor der allgemeinen Basisklasse f"ur SingleTab-Dialoge;
770     ID f"ur das ini-file wird "ubergeben.
771 */
772 
773     SfxModalDialog( pParent, nUniqueId, WinBits( WB_STDMODAL | WB_3DLOOK ) ),
774 
775     pOKBtn          ( 0 ),
776     pCancelBtn      ( 0 ),
777     pHelpBtn        ( 0 ),
778     pImpl           ( new SingleTabDlgImpl )
779 {
780     DBG_WARNING( "please use the ctor with ViewFrame" );
781     SetInputSet( &rSet );
782 }
783 
784 // -----------------------------------------------------------------------
785 
786 SfxSingleTabDialog::SfxSingleTabDialog
787 (
788     Window* pParent,
789     sal_uInt16 nUniqueId,
790     const SfxItemSet* pInSet
791 )
792 
793 /*      [Beschreibung]
794 
795     Konstruktor der allgemeinen Basisklasse f"ur SingleTab-Dialoge;
796     ID f"ur das ini-file wird "ubergeben.
797     Sollte nicht mehr benutzt werden.
798  */
799 
800 :   SfxModalDialog( pParent, nUniqueId, WinBits( WB_STDMODAL | WB_3DLOOK ) ),
801 
802     pOKBtn          ( 0 ),
803     pCancelBtn      ( 0 ),
804     pHelpBtn        ( 0 ),
805     pImpl           ( new SingleTabDlgImpl )
806 {
807     DBG_WARNING( "bitte den Ctor mit ViewFrame verwenden" );
808     SetInputSet( pInSet );
809 }
810 
811 // -----------------------------------------------------------------------
812 
813 SfxSingleTabDialog::SfxSingleTabDialog
814 (
815     Window* pParent,
816     sal_uInt16 nUniqueId,
817     const String& rInfoURL
818 )
819 
820 /*      [Beschreibung]
821 
822     Konstruktor der allgemeinen Basisklasse f"ur SingleTab-Dialoge;
823     ID f"ur das ini-file wird "ubergeben.
824  */
825 
826 :   SfxModalDialog( pParent, nUniqueId, WinBits( WB_STDMODAL | WB_3DLOOK ) ),
827 
828     pOKBtn          ( NULL ),
829     pCancelBtn      ( NULL ),
830     pHelpBtn        ( NULL ),
831     pImpl           ( new SingleTabDlgImpl )
832 {
833     pImpl->m_sInfoURL = rInfoURL;
834 }
835 
836 // -----------------------------------------------------------------------
837 
838 SfxSingleTabDialog::~SfxSingleTabDialog()
839 {
840     delete pOKBtn;
841     delete pCancelBtn;
842     delete pHelpBtn;
843     delete pImpl->m_pTabPage;
844     delete pImpl->m_pSfxPage;
845     delete pImpl->m_pLine;
846     delete pImpl->m_pInfoImage;
847     delete pImpl;
848 }
849 
850 // -----------------------------------------------------------------------
851 
852 void SfxSingleTabDialog::SetPage( TabPage* pNewPage )
853 {
854     if ( !pImpl->m_pLine )
855         pImpl->m_pLine = new FixedLine( this );
856 
857     if ( !pOKBtn )
858     {
859         pOKBtn = new OKButton( this, WB_DEFBUTTON );
860         pOKBtn->SetClickHdl( LINK( this, SfxSingleTabDialog, OKHdl_Impl ) );
861     }
862 
863     if ( pImpl->m_sInfoURL.Len() > 0 && !pImpl->m_pInfoImage )
864     {
865         pImpl->m_pInfoImage = new ::svt::FixedHyperlinkImage( this );
866         Image aInfoImage = Image( SfxResId( IMG_INFO ) );
867         Size aImageSize = aInfoImage.GetSizePixel();
868         aImageSize.Width() += 4;
869         aImageSize.Height() += 4;
870         pImpl->m_pInfoImage->SetSizePixel( aImageSize );
871         pImpl->m_pInfoImage->SetImage( aInfoImage );
872         pImpl->m_pInfoImage->SetURL( pImpl->m_sInfoURL );
873         pImpl->m_pInfoImage->SetClickHdl( pImpl->m_aInfoLink );
874     }
875 
876     if ( pImpl->m_pTabPage )
877         delete pImpl->m_pTabPage;
878     if ( pImpl->m_pSfxPage )
879         delete pImpl->m_pSfxPage;
880     pImpl->m_pTabPage = pNewPage;
881 
882     if ( pImpl->m_pTabPage )
883     {
884         // Gr"ossen und Positionen anpassen
885         pImpl->m_pTabPage->SetPosPixel( Point() );
886         Size aOutSz( pImpl->m_pTabPage->GetSizePixel() );
887         Size aOffSz = LogicToPixel( Size( RSC_SP_CTRL_X, RSC_SP_CTRL_Y ), MAP_APPFONT );
888         Size aFLSz = LogicToPixel( Size( aOutSz.Width(), RSC_CD_FIXEDLINE_HEIGHT ) );
889         Size aBtnSz = LogicToPixel( Size( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ), MAP_APPFONT );
890 
891         Point aPnt( 0, aOutSz.Height() );
892         pImpl->m_pLine->SetPosSizePixel( aPnt, aFLSz );
893         aPnt.X() = aOutSz.Width() - aOffSz.Width() - aBtnSz.Width();
894         aPnt.Y() +=  aFLSz.Height() + ( aOffSz.Height() / 2 );
895         pOKBtn->SetPosSizePixel( aPnt, aBtnSz );
896 
897         if ( pImpl->m_pInfoImage )
898         {
899             aPnt.X() = aOffSz.Width();
900             long nDelta = ( pImpl->m_pInfoImage->GetSizePixel().Height() - aBtnSz.Height() ) / 2;
901             aPnt.Y() -= nDelta;
902             pImpl->m_pInfoImage->SetPosPixel( aPnt );
903             pImpl->m_pInfoImage->Show();
904         }
905 
906         aOutSz.Height() += aFLSz.Height() + ( aOffSz.Height() / 2 ) + aBtnSz.Height() + aOffSz.Height();
907         SetOutputSizePixel( aOutSz );
908 
909         pImpl->m_pLine->Show();
910         pOKBtn->Show();
911         pImpl->m_pTabPage->Show();
912 
913         // Text der TabPage in den Dialog setzen
914         SetText( pImpl->m_pTabPage->GetText() );
915 
916         // Dialog bekommt HelpId der TabPage
917         SetHelpId( pImpl->m_pTabPage->GetHelpId() );
918         SetUniqueId( pImpl->m_pTabPage->GetUniqueId() );
919     }
920 }
921 
922 // -----------------------------------------------------------------------
923 
924 void SfxSingleTabDialog::SetTabPage( SfxTabPage* pTabPage,
925                                      GetTabPageRanges pRangesFunc )
926 /*      [Beschreibung]
927 
928     Setzen einer (neuen) TabPage; eine bereits vorhandene Page
929     wird gel"oscht.
930     Die "ubergebene Page wird durch Aufruf von Reset() mit dem
931     initial "ubergebenen Itemset initialisiert.
932 */
933 
934 {
935     if ( !pOKBtn )
936     {
937         pOKBtn = new OKButton( this, WB_DEFBUTTON );
938         pOKBtn->SetClickHdl( LINK( this, SfxSingleTabDialog, OKHdl_Impl ) );
939     }
940     if ( !pCancelBtn )
941         pCancelBtn = new CancelButton( this );
942     if ( !pHelpBtn )
943         pHelpBtn = new HelpButton( this );
944 
945     if ( pImpl->m_pTabPage )
946         delete pImpl->m_pTabPage;
947     if ( pImpl->m_pSfxPage )
948         delete pImpl->m_pSfxPage;
949     pImpl->m_pSfxPage = pTabPage;
950     fnGetRanges = pRangesFunc;
951 
952     if ( pImpl->m_pSfxPage )
953     {
954         // erstmal die User-Daten besorgen, dann erst Reset()
955         SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( GetUniqId() ) );
956         String sUserData;
957         Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME );
958         OUString aTemp;
959         if ( aUserItem >>= aTemp )
960             sUserData = String( aTemp );
961         pImpl->m_pSfxPage->SetUserData( sUserData );
962         pImpl->m_pSfxPage->Reset( *GetInputItemSet() );
963         pImpl->m_pSfxPage->Show();
964 
965         // Gr"ossen und Positionen anpassen
966         pImpl->m_pSfxPage->SetPosPixel( Point() );
967         Size aOutSz( pImpl->m_pSfxPage->GetSizePixel() );
968         Size aBtnSiz = LogicToPixel( Size( 50, 14 ), MAP_APPFONT );
969         Point aPnt( aOutSz.Width(), LogicToPixel( Point( 0, 6 ), MAP_APPFONT ).Y() );
970         aOutSz.Width() += aBtnSiz.Width() + LogicToPixel( Size( 6, 0 ), MAP_APPFONT ).Width();
971         SetOutputSizePixel( aOutSz );
972         pOKBtn->SetPosSizePixel( aPnt, aBtnSiz );
973         pOKBtn->Show();
974         aPnt.Y() = LogicToPixel( Point( 0, 23 ), MAP_APPFONT ).Y();
975         pCancelBtn->SetPosSizePixel( aPnt, aBtnSiz );
976         pCancelBtn->Show();
977         aPnt.Y() = LogicToPixel( Point( 0, 43 ), MAP_APPFONT ).Y();
978         pHelpBtn->SetPosSizePixel( aPnt, aBtnSiz );
979 
980         if ( Help::IsContextHelpEnabled() )
981             pHelpBtn->Show();
982 
983         // Text der TabPage in den Dialog setzen
984         SetText( pImpl->m_pSfxPage->GetText() );
985 
986         // Dialog bekommt HelpId der TabPage
987         SetHelpId( pImpl->m_pSfxPage->GetHelpId() );
988         SetUniqueId( pImpl->m_pSfxPage->GetUniqueId() );
989     }
990 }
991 
992 // -----------------------------------------------------------------------
993 
994 void SfxSingleTabDialog::SetInfoLink( const Link& rLink )
995 {
996     pImpl->m_aInfoLink = rLink;
997 }
998 
999 //--------------------------------------------------------------------
1000 // Vergleichsfunktion fuer qsort
1001 
1002 #ifdef WNT
1003 int __cdecl BaseDlgsCmpUS_Impl( const void* p1, const void* p2 )
1004 #else
1005 #if defined(OS2) && defined(ICC)
1006 int _Optlink BaseDlgsCmpUS_Impl(        const void* p1, const void* p2 )
1007 #else
1008 extern "C" int BaseDlgsCmpUS_Impl( const void* p1, const void* p2 )
1009 #endif
1010 #endif
1011 {
1012     return *(sal_uInt16*)p1 - *(sal_uInt16*)p2;
1013 }
1014 
1015 // -----------------------------------------------------------------------
1016 
1017 /*
1018     Bildet das Set "uber die Ranges der Page. Die Page muss die statische
1019     Methode f"ur das Erfragen ihrer Ranges bei SetTabPage angegeben haben,
1020     liefert also ihr Set onDemand.
1021  */
1022 const sal_uInt16* SfxSingleTabDialog::GetInputRanges( const SfxItemPool& rPool )
1023 {
1024     if ( GetInputItemSet() )
1025     {
1026         DBG_ERROR( "Set bereits vorhanden!" );
1027         return GetInputItemSet()->GetRanges();
1028     }
1029 
1030     if ( pRanges )
1031         return pRanges;
1032     SvUShorts aUS(16, 16);
1033 
1034     if ( fnGetRanges)
1035     {
1036         const sal_uInt16 *pTmpRanges = (fnGetRanges)();
1037         const sal_uInt16 *pIter = pTmpRanges;
1038         sal_uInt16 nLen;
1039         for ( nLen = 0; *pIter; ++nLen, ++pIter )
1040             ;
1041         aUS.Insert( pTmpRanges, nLen, aUS.Count() );
1042     }
1043 
1044     //! Doppelte Ids entfernen?
1045     sal_uInt16 nCount = aUS.Count();
1046 
1047     for ( sal_uInt16 i = 0; i < nCount; ++i )
1048         aUS[i] = rPool.GetWhich( aUS[i]) ;
1049 
1050     // sortieren
1051     if ( aUS.Count() > 1 )
1052         qsort( (void*)aUS.GetData(), aUS.Count(), sizeof(sal_uInt16), BaseDlgsCmpUS_Impl );
1053 
1054     pRanges = new sal_uInt16[aUS.Count() + 1];
1055     memcpy( pRanges, aUS.GetData(), sizeof(sal_uInt16) * aUS.Count() );
1056     pRanges[aUS.Count()] = 0;
1057     return pRanges;
1058 }
1059 
1060