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