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