xref: /aoo41x/main/sfx2/source/dialog/basedlgs.cxx (revision cdf0e10c)
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