1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dlgctrl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/debug.hxx>
34 #include <vcl/svdata.hxx>
35 #include <vcl/event.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/tabpage.hxx>
38 #include <vcl/tabctrl.hxx>
39 #include <vcl/button.hxx>
40 #include <vcl/window.h>
42 #include <vcl/unohelp.hxx>
43 #include <com/sun/star/i18n/XCharacterClassification.hpp>
45 using namespace ::com::sun::star
;
47 // =======================================================================
49 static BOOL
ImplHasIndirectTabParent( Window
* pWindow
)
51 // The window has inderect tab parent if it is included in tab hierarchy
52 // of the indirect parent window
54 return ( pWindow
&& pWindow
->GetParent()
55 && ( pWindow
->GetParent()->ImplGetWindow()->GetStyle() & WB_CHILDDLGCTRL
) );
58 // -----------------------------------------------------------------------
60 static Window
* ImplGetTopParentOfTabHierarchy( Window
* pParent
)
62 // The method allows to find the most close parent containing all the
63 // window from the current tab-hierarchy
64 // The direct parent should be provided as a parameter here
66 Window
* pResult
= pParent
;
70 while ( pResult
->GetParent() && ( pResult
->ImplGetWindow()->GetStyle() & WB_CHILDDLGCTRL
) )
71 pResult
= pResult
->GetParent();
77 // -----------------------------------------------------------------------
79 static Window
* ImplGetSubChildWindow( Window
* pParent
, USHORT n
, USHORT
& nIndex
)
81 Window
* pTabPage
= NULL
;
82 Window
* pFoundWindow
= NULL
;
84 Window
* pWindow
= pParent
->GetWindow( WINDOW_FIRSTCHILD
);
85 Window
* pNextWindow
= pWindow
;
88 pWindow
= pWindow
->ImplGetWindow();
90 // Unsichtbare und disablte Fenster werden uebersprungen
91 if ( pTabPage
|| pWindow
->IsVisible() )
93 // Wenn das letzte Control ein TabControl war, wird von
94 // diesem die TabPage genommen
97 pFoundWindow
= ImplGetSubChildWindow( pTabPage
, n
, nIndex
);
102 pFoundWindow
= pWindow
;
104 // Bei einem TabControl sich die aktuelle TabPage merken,
105 // damit diese dann genommen wird
106 if ( pWindow
->GetType() == WINDOW_TABCONTROL
)
108 TabControl
* pTabControl
= ((TabControl
*)pWindow
);
109 // Feststellen, ob TabPage Child vom TabControl ist
110 // und auch noch existiert (deshalb durch Vergleich,
111 // indem alle ChildFenster getestet werden). Denn es
112 // kann sein, das TabPages schon in einem Dialog-Dtor
113 // zerstoert wurden, obwohl das TabControl noch
115 TabPage
* pTempTabPage
= pTabControl
->GetTabPage( pTabControl
->GetCurPageId() );
118 Window
* pTempWindow
= pTabControl
->GetWindow( WINDOW_FIRSTCHILD
);
119 while ( pTempWindow
)
121 if ( pTempWindow
->ImplGetWindow() == pTempTabPage
)
123 pTabPage
= pTempTabPage
;
126 pTempWindow
= pTempWindow
->GetWindow( WINDOW_NEXT
);
130 else if ( ( pWindow
->GetStyle() & WB_DIALOGCONTROL
)
131 || ( pWindow
->GetStyle() & WB_CHILDDLGCTRL
) )
132 pFoundWindow
= ImplGetSubChildWindow( pWindow
, n
, nIndex
);
144 pWindow
= pNextWindow
->GetWindow( WINDOW_NEXT
);
145 pNextWindow
= pWindow
;
153 // -----------------------------------------------------------------------
155 static Window
* ImplGetChildWindow( Window
* pParent
, USHORT n
, USHORT
& nIndex
, BOOL bTestEnable
)
157 pParent
= ImplGetTopParentOfTabHierarchy( pParent
);
160 Window
* pWindow
= ImplGetSubChildWindow( pParent
, n
, nIndex
);
164 while ( pWindow
&& (!pWindow
->IsEnabled() || !pWindow
->IsInputEnabled()) )
168 pWindow
= ImplGetSubChildWindow( pParent
, n2
, nIndex
);
173 if ( (nIndex
< n2
) && n
)
179 pWindow
= ImplGetSubChildWindow( pParent
, n
, nIndex
);
181 while ( pWindow
&& n
&& (!pWindow
->IsEnabled() || !pWindow
->IsInputEnabled()) );
187 // -----------------------------------------------------------------------
189 static Window
* ImplGetNextWindow( Window
* pParent
, USHORT n
, USHORT
& nIndex
, BOOL bTestEnable
)
191 Window
* pWindow
= ImplGetChildWindow( pParent
, n
+1, nIndex
, bTestEnable
);
195 pWindow
= ImplGetChildWindow( pParent
, n
, nIndex
, bTestEnable
);
200 // -----------------------------------------------------------------------
202 Window
* Window::ImplGetDlgWindow( USHORT nIndex
, USHORT nType
,
203 USHORT nFormStart
, USHORT nFormEnd
,
206 DBG_ASSERT( (nIndex
>= nFormStart
) && (nIndex
<= nFormEnd
),
207 "Window::ImplGetDlgWindow() - nIndex not in Form" );
209 Window
* pWindow
= NULL
;
214 if ( nType
== DLGWINDOW_PREV
)
219 if ( i
> nFormStart
)
223 pWindow
= ImplGetChildWindow( this, i
, nTemp
, TRUE
);
226 if ( (i
== nTemp
) && (pWindow
->GetStyle() & WB_TABSTOP
) )
229 while ( i
!= nIndex
);
234 pWindow
= ImplGetChildWindow( this, i
, i
, (nType
== DLGWINDOW_FIRST
) );
239 if ( nType
== DLGWINDOW_NEXT
)
243 pWindow
= ImplGetNextWindow( this, i
, i
, TRUE
);
244 if ( (i
> nFormEnd
) || (i
< nFormStart
) )
245 pWindow
= ImplGetChildWindow( this, nFormStart
, i
, TRUE
);
248 pWindow
= ImplGetChildWindow( this, nFormStart
, i
, TRUE
);
253 // 2ten Index mitfuehren, falls alle Controls disablte
254 USHORT nStartIndex2
= i
;
255 USHORT nOldIndex
= i
+1;
259 if ( pWindow
->GetStyle() & WB_TABSTOP
)
261 if( i
== nOldIndex
) // only disabled controls ?
267 if ( (i
> nFormEnd
) || (i
< nFormStart
) )
268 pWindow
= ImplGetChildWindow( this, nFormStart
, i
, TRUE
);
270 pWindow
= ImplGetNextWindow( this, i
, i
, TRUE
);
272 while ( (i
!= nStartIndex
) && (i
!= nStartIndex2
) );
274 if ( (i
== nStartIndex2
) &&
275 (!(pWindow
->GetStyle() & WB_TABSTOP
) || !pWindow
->IsEnabled()) )
280 if ( nType
== DLGWINDOW_FIRST
)
284 if ( pWindow
->GetType() == WINDOW_TABCONTROL
)
286 Window
* pNextWindow
= ImplGetDlgWindow( i
, DLGWINDOW_NEXT
);
289 if ( pWindow
->IsChild( pNextWindow
) )
290 pWindow
= pNextWindow
;
294 if ( !(pWindow
->GetStyle() & WB_TABSTOP
) )
306 // -----------------------------------------------------------------------
308 static Window
* ImplFindDlgCtrlWindow( Window
* pParent
, Window
* pWindow
, USHORT
& rIndex
,
309 USHORT
& rFormStart
, USHORT
& rFormEnd
)
312 Window
* pSecondWindow
= NULL
;
313 Window
* pTempWindow
= NULL
;
315 USHORT nSecond_i
= 0;
316 USHORT nFormStart
= 0;
317 USHORT nSecondFormStart
= 0;
320 // Focus-Fenster in der Child-Liste suchen
321 Window
* pFirstChildWindow
= pSWindow
= ImplGetChildWindow( pParent
, 0, i
, FALSE
);
323 if( pWindow
== NULL
)
328 // the DialogControlStart mark is only accepted for the direct children
329 if ( !ImplHasIndirectTabParent( pSWindow
)
330 && pSWindow
->ImplGetWindow()->IsDialogControlStart() )
333 // SecondWindow wegen zusammengesetzten Controls wie
334 // ComboBoxen und Feldern
335 if ( pSWindow
->ImplIsWindowOrChild( pWindow
) )
337 pSecondWindow
= pSWindow
;
339 nSecondFormStart
= nFormStart
;
340 if ( pSWindow
== pWindow
)
344 pSWindow
= ImplGetNextWindow( pParent
, i
, i
, FALSE
);
351 // Fenster nicht gefunden, dann koennen wir auch keine
352 // Steuerung uebernehmen
353 if ( !pSecondWindow
)
357 pSWindow
= pSecondWindow
;
359 nFormStart
= nSecondFormStart
;
363 // Start-Daten setzen
365 rFormStart
= nFormStart
;
367 // Formularende suchen
368 nFormEnd
= nFormStart
;
369 pTempWindow
= pSWindow
;
370 sal_Int32 nIteration
= 0;
374 pTempWindow
= ImplGetNextWindow( pParent
, i
, i
, FALSE
);
376 // the DialogControlStart mark is only accepted for the direct children
378 || ( pTempWindow
&& !ImplHasIndirectTabParent( pTempWindow
)
379 && pTempWindow
->ImplGetWindow()->IsDialogControlStart() ) )
382 if ( pTempWindow
&& pTempWindow
== pFirstChildWindow
)
384 // It is possible to go through the begin of hierarchy once
385 // while looking for DialogControlStart mark.
386 // If it happens second time, it looks like an endless loop,
387 // that should be impossible, but just for the case...
389 if ( nIteration
>= 2 )
391 // this is an unexpected scenario
392 DBG_ASSERT( FALSE
, "It seems to be an endless loop!" );
398 while ( pTempWindow
);
404 // -----------------------------------------------------------------------
406 static Window
* ImplFindAccelWindow( Window
* pParent
, USHORT
& rIndex
, xub_Unicode cCharCode
,
407 USHORT nFormStart
, USHORT nFormEnd
, BOOL bCheckEnable
= TRUE
)
409 DBG_ASSERT( (rIndex
>= nFormStart
) && (rIndex
<= nFormEnd
),
410 "Window::ImplFindAccelWindow() - rIndex not in Form" );
412 xub_Unicode cCompareChar
;
413 USHORT nStart
= rIndex
;
418 // MT: Where can we keep the CharClass?!
419 static uno::Reference
< i18n::XCharacterClassification
> xCharClass
;
420 if ( !xCharClass
.is() )
421 xCharClass
= vcl::unohelper::CreateCharacterClassification();
423 const ::com::sun::star::lang::Locale
& rLocale
= Application::GetSettings().GetUILocale();
424 cCharCode
= xCharClass
->toUpper( String(cCharCode
), 0, 1, rLocale
)[0];
427 pWindow
= ImplGetNextWindow( pParent
, i
, i
, TRUE
);
429 pWindow
= ImplGetChildWindow( pParent
, nFormStart
, i
, TRUE
);
430 while( bSearch
&& pWindow
)
432 const XubString aStr
= pWindow
->GetText();
433 USHORT nPos
= aStr
.Search( '~' );
434 while ( nPos
!= STRING_NOTFOUND
)
436 cCompareChar
= aStr
.GetChar( nPos
+1 );
437 cCompareChar
= xCharClass
->toUpper( String(cCompareChar
), 0, 1, rLocale
)[0];
438 if ( cCompareChar
== cCharCode
)
440 // Bei Static-Controls auf das naechste Controlm weiterschalten
441 if ( (pWindow
->GetType() == WINDOW_FIXEDTEXT
) ||
442 (pWindow
->GetType() == WINDOW_FIXEDLINE
) ||
443 (pWindow
->GetType() == WINDOW_GROUPBOX
) )
444 pWindow
= pParent
->ImplGetDlgWindow( i
, DLGWINDOW_NEXT
);
448 nPos
= aStr
.Search( '~', nPos
+1 );
451 // #i93011# it would have made sense to have this really recursive
452 // right from the start. However this would cause unpredictable side effects now
453 // so instead we have a style bit for some child windows, that want their
454 // children checked for accelerators
455 if( (pWindow
->GetStyle() & WB_CHILDDLGCTRL
) != 0 )
458 USHORT nChildFormStart
;
459 USHORT nChildFormEnd
;
461 // get form start and end
462 ::ImplFindDlgCtrlWindow( pWindow
, NULL
,
463 nChildIndex
, nChildFormStart
, nChildFormEnd
);
464 Window
* pAccelWin
= ImplFindAccelWindow( pWindow
, nChildIndex
, cCharCode
,
465 nChildFormStart
, nChildFormEnd
,
476 pWindow
= ImplGetNextWindow( pParent
, i
, i
, bCheckEnable
);
478 pWindow
= ImplGetChildWindow( pParent
, nFormStart
, i
, bCheckEnable
);
481 pWindow
= ImplGetChildWindow( pParent
, nFormStart
, i
, bCheckEnable
);
487 // -----------------------------------------------------------------------
489 void Window::ImplControlFocus( USHORT nFlags
)
491 if ( nFlags
& GETFOCUS_MNEMONIC
)
493 if ( GetType() == WINDOW_RADIOBUTTON
)
495 if ( !((RadioButton
*)this)->IsChecked() )
496 ((RadioButton
*)this)->ImplCallClick( TRUE
, nFlags
);
498 ImplGrabFocus( nFlags
);
502 ImplGrabFocus( nFlags
);
503 if ( nFlags
& GETFOCUS_UNIQUEMNEMONIC
)
505 if ( GetType() == WINDOW_CHECKBOX
)
506 ((CheckBox
*)this)->ImplCheck();
507 else if ( mpWindowImpl
->mbPushButton
)
509 ((PushButton
*)this)->SetPressed( TRUE
);
510 ((PushButton
*)this)->SetPressed( FALSE
);
511 ((PushButton
*)this)->Click();
518 if ( GetType() == WINDOW_RADIOBUTTON
)
520 if ( !((RadioButton
*)this)->IsChecked() )
521 ((RadioButton
*)this)->ImplCallClick( TRUE
, nFlags
);
523 ImplGrabFocus( nFlags
);
526 ImplGrabFocus( nFlags
);
530 // -----------------------------------------------------------------------
532 BOOL
Window::ImplDlgCtrl( const KeyEvent
& rKEvt
, BOOL bKeyInput
)
534 KeyCode aKeyCode
= rKEvt
.GetKeyCode();
535 USHORT nKeyCode
= aKeyCode
.GetCode();
538 Window
* pButtonWindow
;
546 USHORT nDlgCtrlFlags
;
548 // Ohne Focus-Window koennen wir auch keine Steuerung uebernehmen
549 Window
* pFocusWindow
= Application::GetFocusWindow();
550 if ( !pFocusWindow
|| !ImplIsWindowOrChild( pFocusWindow
) )
553 // Focus-Fenster in der Child-Liste suchen
554 pSWindow
= ::ImplFindDlgCtrlWindow( this, pFocusWindow
,
555 nIndex
, nFormStart
, nFormEnd
);
561 pTempWindow
= pSWindow
;
564 nDlgCtrlFlags
|= pTempWindow
->GetDialogControlFlags();
565 if ( pTempWindow
== this )
567 pTempWindow
= pTempWindow
->ImplGetParent();
569 while ( pTempWindow
);
571 pButtonWindow
= NULL
;
573 if ( nKeyCode
== KEY_RETURN
)
575 // Wir suchen zuerst nach einem DefPushButton/CancelButton
576 pButtonWindow
= ImplGetChildWindow( this, nFormStart
, iButton
, TRUE
);
577 iButtonStart
= iButton
;
578 while ( pButtonWindow
)
580 if ( (pButtonWindow
->GetStyle() & WB_DEFBUTTON
) &&
581 pButtonWindow
->mpWindowImpl
->mbPushButton
)
584 pButtonWindow
= ImplGetNextWindow( this, iButton
, iButton
, TRUE
);
585 if ( (iButton
<= iButtonStart
) || (iButton
> nFormEnd
) )
586 pButtonWindow
= NULL
;
589 if ( bKeyInput
&& !pButtonWindow
&& (nDlgCtrlFlags
& WINDOW_DLGCTRL_RETURN
) )
592 USHORT nGetFocusFlags
= GETFOCUS_TAB
;
595 if ( aKeyCode
.IsShift() )
597 nType
= DLGWINDOW_PREV
;
598 nGetFocusFlags
|= GETFOCUS_BACKWARD
;
602 nType
= DLGWINDOW_NEXT
;
603 nGetFocusFlags
|= GETFOCUS_FORWARD
;
606 pTempWindow
= ImplGetDlgWindow( i
, nType
, nFormStart
, nFormEnd
, &nNewIndex
);
607 while ( pTempWindow
&& (pTempWindow
!= pSWindow
) )
609 if ( !pTempWindow
->mpWindowImpl
->mbPushButton
)
611 // Around-Flag ermitteln
612 if ( nType
== DLGWINDOW_PREV
)
614 if ( nNewIndex
> iStart
)
615 nGetFocusFlags
|= GETFOCUS_AROUND
;
619 if ( nNewIndex
< iStart
)
620 nGetFocusFlags
|= GETFOCUS_AROUND
;
622 pTempWindow
->ImplControlFocus( nGetFocusFlags
);
628 pTempWindow
= ImplGetDlgWindow( i
, nType
, nFormStart
, nFormEnd
, &nNewIndex
);
630 if ( (i
<= iStart
) || (i
> nFormEnd
) )
633 // Wenn es das gleiche Fenster ist, ein Get/LoseFocus
634 // simulieren, falls AROUND ausgewertet wird
635 if ( pTempWindow
&& (pTempWindow
== pSWindow
) )
637 NotifyEvent
aNEvt1( EVENT_LOSEFOCUS
, pSWindow
);
638 if ( !ImplCallPreNotify( aNEvt1
) )
639 pSWindow
->LoseFocus();
640 pSWindow
->mpWindowImpl
->mnGetFocusFlags
= nGetFocusFlags
| GETFOCUS_AROUND
;
641 NotifyEvent
aNEvt2( EVENT_GETFOCUS
, pSWindow
);
642 if ( !ImplCallPreNotify( aNEvt2
) )
643 pSWindow
->GetFocus();
644 pSWindow
->mpWindowImpl
->mnGetFocusFlags
= 0;
649 else if ( nKeyCode
== KEY_ESCAPE
)
651 // Wir suchen zuerst nach einem DefPushButton/CancelButton
652 pButtonWindow
= ImplGetChildWindow( this, nFormStart
, iButton
, TRUE
);
653 iButtonStart
= iButton
;
654 while ( pButtonWindow
)
656 if ( pButtonWindow
->GetType() == WINDOW_CANCELBUTTON
)
659 pButtonWindow
= ImplGetNextWindow( this, iButton
, iButton
, TRUE
);
660 if ( (iButton
<= iButtonStart
) || (iButton
> nFormEnd
) )
661 pButtonWindow
= NULL
;
664 if ( bKeyInput
&& mpWindowImpl
->mpDlgCtrlDownWindow
)
666 if ( mpWindowImpl
->mpDlgCtrlDownWindow
!= pButtonWindow
)
668 ((PushButton
*)mpWindowImpl
->mpDlgCtrlDownWindow
)->SetPressed( FALSE
);
669 mpWindowImpl
->mpDlgCtrlDownWindow
= NULL
;
674 else if ( bKeyInput
)
676 if ( nKeyCode
== KEY_TAB
)
678 // keine Alt-Taste abfangen, wegen Windows
679 if ( !aKeyCode
.IsMod2() )
682 USHORT nGetFocusFlags
= GETFOCUS_TAB
;
684 BOOL bFormular
= FALSE
;
686 // Bei Ctrl-Tab erstmal testen, ob zwischen Formularen
687 // gesprungen werden soll
688 if ( aKeyCode
.IsMod1() )
691 Window
* pFormularFirstWindow
= NULL
;
692 Window
* pLastFormularFirstWindow
= NULL
;
693 pTempWindow
= ImplGetChildWindow( this, 0, iTemp
, FALSE
);
694 Window
* pPrevFirstFormularFirstWindow
= NULL
;
695 Window
* pFirstFormularFirstWindow
= pTempWindow
;
696 while ( pTempWindow
)
698 if ( pTempWindow
->ImplGetWindow()->IsDialogControlStart() )
702 if ( aKeyCode
.IsShift() )
704 if ( iTemp
<= nIndex
)
705 pFormularFirstWindow
= pPrevFirstFormularFirstWindow
;
706 pPrevFirstFormularFirstWindow
= pTempWindow
;
710 if ( (iTemp
> nIndex
) && !pFormularFirstWindow
)
711 pFormularFirstWindow
= pTempWindow
;
713 pLastFormularFirstWindow
= pTempWindow
;
716 pTempWindow
= ImplGetNextWindow( this, iTemp
, iTemp
, FALSE
);
723 if ( !pFormularFirstWindow
)
725 if ( aKeyCode
.IsShift() )
726 pFormularFirstWindow
= pLastFormularFirstWindow
;
728 pFormularFirstWindow
= pFirstFormularFirstWindow
;
731 USHORT nFoundFormStart
= 0;
732 USHORT nFoundFormEnd
= 0;
733 USHORT nTempIndex
= 0;
734 if ( ::ImplFindDlgCtrlWindow( this, pFormularFirstWindow
, nTempIndex
,
735 nFoundFormStart
, nFoundFormEnd
) )
737 nTempIndex
= nFoundFormStart
;
738 pFormularFirstWindow
= ImplGetDlgWindow( nTempIndex
, DLGWINDOW_FIRST
, nFoundFormStart
, nFoundFormEnd
);
739 if ( pFormularFirstWindow
)
741 pFormularFirstWindow
->ImplControlFocus();
750 // Only use Ctrl-TAB if it was allowed for the whole
751 // dialog or for the current control (#103667#)
752 if ( !aKeyCode
.IsMod1() || (nDlgCtrlFlags
& WINDOW_DLGCTRL_MOD1TAB
) ||
753 ( pSWindow
->GetStyle() & WINDOW_DLGCTRL_MOD1TAB
) )
755 if ( aKeyCode
.IsShift() )
757 nType
= DLGWINDOW_PREV
;
758 nGetFocusFlags
|= GETFOCUS_BACKWARD
;
762 nType
= DLGWINDOW_NEXT
;
763 nGetFocusFlags
|= GETFOCUS_FORWARD
;
765 Window
* pWindow
= ImplGetDlgWindow( i
, nType
, nFormStart
, nFormEnd
, &nNewIndex
);
766 // Wenn es das gleiche Fenster ist, ein Get/LoseFocus
767 // simulieren, falls AROUND ausgewertet wird
768 if ( pWindow
== pSWindow
)
770 NotifyEvent
aNEvt1( EVENT_LOSEFOCUS
, pSWindow
);
771 if ( !ImplCallPreNotify( aNEvt1
) )
772 pSWindow
->LoseFocus();
773 pSWindow
->mpWindowImpl
->mnGetFocusFlags
= nGetFocusFlags
| GETFOCUS_AROUND
;
774 NotifyEvent
aNEvt2( EVENT_GETFOCUS
, pSWindow
);
775 if ( !ImplCallPreNotify( aNEvt2
) )
776 pSWindow
->GetFocus();
777 pSWindow
->mpWindowImpl
->mnGetFocusFlags
= 0;
782 // Around-Flag ermitteln
783 if ( nType
== DLGWINDOW_PREV
)
786 nGetFocusFlags
|= GETFOCUS_AROUND
;
791 nGetFocusFlags
|= GETFOCUS_AROUND
;
793 pWindow
->ImplControlFocus( nGetFocusFlags
);
800 else if ( (nKeyCode
== KEY_LEFT
) || (nKeyCode
== KEY_UP
) )
802 Window
* pWindow
= pSWindow
;
803 WinBits nStyle
= pSWindow
->GetStyle();
804 if ( !(nStyle
& WB_GROUP
) )
806 pWindow
= pWindow
->GetWindow( WINDOW_PREV
);
809 pWindow
= pWindow
->ImplGetWindow();
811 nStyle
= pWindow
->GetStyle();
813 if ( pWindow
->IsVisible() && pWindow
->IsEnabled() && pWindow
->IsInputEnabled() )
815 if ( pWindow
!= pSWindow
)
816 pWindow
->ImplControlFocus( GETFOCUS_CURSOR
| GETFOCUS_BACKWARD
);
820 if ( nStyle
& WB_GROUP
)
823 pWindow
= pWindow
->GetWindow( WINDOW_PREV
);
827 else if ( (nKeyCode
== KEY_RIGHT
) || (nKeyCode
== KEY_DOWN
) )
831 pWindow
= pSWindow
->GetWindow( WINDOW_NEXT
);
834 pWindow
= pWindow
->ImplGetWindow();
836 nStyle
= pWindow
->GetStyle();
838 if ( nStyle
& WB_GROUP
)
841 if ( pWindow
->IsVisible() && pWindow
->IsEnabled() && pWindow
->IsInputEnabled() )
843 pWindow
->ImplControlFocus( GETFOCUS_CURSOR
| GETFOCUS_BACKWARD
);
847 pWindow
= pWindow
->GetWindow( WINDOW_NEXT
);
850 else if ( !aKeyCode
.IsMod1() ) // no ctrl pressed - those are
851 // application-wide shortcuts
852 // we want to let pass
854 xub_Unicode c
= rKEvt
.GetCharCode();
857 pSWindow
= ::ImplFindAccelWindow( this, i
, c
, nFormStart
, nFormEnd
);
860 USHORT nGetFocusFlags
= GETFOCUS_MNEMONIC
;
861 if ( pSWindow
== ::ImplFindAccelWindow( this, i
, c
, nFormStart
, nFormEnd
) )
862 nGetFocusFlags
|= GETFOCUS_UNIQUEMNEMONIC
;
863 pSWindow
->ImplControlFocus( nGetFocusFlags
);
870 if ( pButtonWindow
&& pButtonWindow
->IsVisible() && pButtonWindow
->IsEnabled() && pButtonWindow
->IsInputEnabled() )
874 if ( mpWindowImpl
->mpDlgCtrlDownWindow
&& (mpWindowImpl
->mpDlgCtrlDownWindow
!= pButtonWindow
) )
876 ((PushButton
*)mpWindowImpl
->mpDlgCtrlDownWindow
)->SetPressed( FALSE
);
877 mpWindowImpl
->mpDlgCtrlDownWindow
= NULL
;
880 ((PushButton
*)pButtonWindow
)->SetPressed( TRUE
);
881 mpWindowImpl
->mpDlgCtrlDownWindow
= pButtonWindow
;
883 else if ( mpWindowImpl
->mpDlgCtrlDownWindow
== pButtonWindow
)
885 mpWindowImpl
->mpDlgCtrlDownWindow
= NULL
;
886 ((PushButton
*)pButtonWindow
)->SetPressed( FALSE
);
887 ((PushButton
*)pButtonWindow
)->Click();
896 // -----------------------------------------------------------------------
898 // checks if this window has dialog control
899 BOOL
Window::ImplHasDlgCtrl()
901 Window
* pDlgCtrlParent
;
904 // lookup window for dialog control
906 pDlgCtrlParent
= ImplGetParent();
907 while ( pDlgCtrlParent
&&
908 !pDlgCtrlParent
->ImplIsOverlapWindow() &&
909 ((pDlgCtrlParent
->GetStyle() & (WB_DIALOGCONTROL
| WB_NODIALOGCONTROL
)) != WB_DIALOGCONTROL
) )
910 pDlgCtrlParent
= pDlgCtrlParent
->ImplGetParent();
912 if ( !pDlgCtrlParent
|| ((pDlgCtrlParent
->GetStyle() & (WB_DIALOGCONTROL
| WB_NODIALOGCONTROL
)) != WB_DIALOGCONTROL
) )
918 void Window::ImplDlgCtrlNextWindow()
920 Window
* pDlgCtrlParent
;
927 // lookup window for dialog control
929 pDlgCtrlParent
= ImplGetParent();
930 while ( pDlgCtrlParent
&&
931 !pDlgCtrlParent
->ImplIsOverlapWindow() &&
932 ((pDlgCtrlParent
->GetStyle() & (WB_DIALOGCONTROL
| WB_NODIALOGCONTROL
)) != WB_DIALOGCONTROL
) )
933 pDlgCtrlParent
= pDlgCtrlParent
->ImplGetParent();
935 if ( !pDlgCtrlParent
|| (GetStyle() & WB_NODIALOGCONTROL
) || ((pDlgCtrlParent
->GetStyle() & (WB_DIALOGCONTROL
| WB_NODIALOGCONTROL
)) != WB_DIALOGCONTROL
) )
938 // lookup window in child list
939 pSWindow
= ::ImplFindDlgCtrlWindow( pDlgCtrlParent
, pDlgCtrl
,
940 nIndex
, nFormStart
, nFormEnd
);
944 Window
* pWindow
= pDlgCtrlParent
->ImplGetDlgWindow( nIndex
, DLGWINDOW_NEXT
, nFormStart
, nFormEnd
);
945 if ( pWindow
&& (pWindow
!= pSWindow
) )
946 pWindow
->ImplControlFocus();
949 // -----------------------------------------------------------------------
951 static void ImplDlgCtrlUpdateDefButton( Window
* pParent
, Window
* pFocusWindow
,
954 PushButton
* pOldDefButton
= NULL
;
955 PushButton
* pNewDefButton
= NULL
;
962 pSWindow
= ::ImplFindDlgCtrlWindow( pParent
, pFocusWindow
, i
, nFormStart
, nFormEnd
);
969 pSWindow
= ImplGetChildWindow( pParent
, nFormStart
, i
, FALSE
);
972 if ( pSWindow
->ImplIsPushButton() )
974 PushButton
* pPushButton
= (PushButton
*)pSWindow
;
975 if ( pPushButton
->ImplIsDefButton() )
976 pOldDefButton
= pPushButton
;
977 if ( pPushButton
->HasChildPathFocus() )
978 pNewDefButton
= pPushButton
;
979 else if ( !pNewDefButton
&& (pPushButton
->GetStyle() & WB_DEFBUTTON
) )
980 pNewDefButton
= pPushButton
;
983 pSWindow
= ImplGetNextWindow( pParent
, i
, i
, FALSE
);
984 if ( !i
|| (i
> nFormEnd
) )
991 Window
* pNewFocusWindow
= Application::GetFocusWindow();
992 if ( !pNewFocusWindow
|| !pParent
->ImplIsWindowOrChild( pNewFocusWindow
) )
993 pNewDefButton
= NULL
;
994 else if ( !::ImplFindDlgCtrlWindow( pParent
, pNewFocusWindow
, i
, nDummy
, nDummy
) ||
995 (i
< nFormStart
) || (i
> nFormEnd
) )
996 pNewDefButton
= NULL
;
999 if ( pOldDefButton
!= pNewDefButton
)
1001 if ( pOldDefButton
)
1002 pOldDefButton
->ImplSetDefButton( FALSE
);
1003 if ( pNewDefButton
)
1004 pNewDefButton
->ImplSetDefButton( TRUE
);
1008 // -----------------------------------------------------------------------
1010 void Window::ImplDlgCtrlFocusChanged( Window
* pWindow
, BOOL bGetFocus
)
1012 if ( mpWindowImpl
->mpDlgCtrlDownWindow
&& !bGetFocus
)
1014 ((PushButton
*)mpWindowImpl
->mpDlgCtrlDownWindow
)->SetPressed( FALSE
);
1015 mpWindowImpl
->mpDlgCtrlDownWindow
= NULL
;
1018 ImplDlgCtrlUpdateDefButton( this, pWindow
, bGetFocus
);
1021 // -----------------------------------------------------------------------
1023 Window
* Window::ImplFindDlgCtrlWindow( Window
* pWindow
)
1029 // Focus-Fenster in der Child-Liste suchen und zurueckgeben
1030 return ::ImplFindDlgCtrlWindow( this, pWindow
, nIndex
, nFormStart
, nFormEnd
);
1034 // -----------------------------------------------------------------------
1036 Window
* Window::GetParentLabelFor( const Window
* ) const
1041 // -----------------------------------------------------------------------
1043 Window
* Window::GetParentLabeledBy( const Window
* ) const
1048 // -----------------------------------------------------------------------
1050 static sal_Unicode
getAccel( const String
& rStr
)
1052 sal_Unicode nChar
= 0;
1056 nPos
= rStr
.Search( '~', nPos
);
1057 if( nPos
!= STRING_NOTFOUND
&& nPos
< rStr
.Len() )
1058 nChar
= rStr
.GetChar( ++nPos
);
1061 } while( nChar
== '~' );
1065 Window
* Window::GetLabelFor() const
1067 if ( mpWindowImpl
->mbDisableAccessibleLabelForRelation
)
1070 Window
* pWindow
= NULL
;
1071 Window
* pFrameWindow
= ImplGetFrameWindow();
1073 WinBits nFrameStyle
= pFrameWindow
->GetStyle();
1074 if( ! ( nFrameStyle
& WB_DIALOGCONTROL
)
1075 || ( nFrameStyle
& WB_NODIALOGCONTROL
)
1079 if ( mpWindowImpl
->mpRealParent
)
1080 pWindow
= mpWindowImpl
->mpRealParent
->GetParentLabelFor( this );
1085 sal_Unicode nAccel
= getAccel( GetText() );
1086 if( GetType() == WINDOW_FIXEDTEXT
||
1087 GetType() == WINDOW_FIXEDLINE
||
1088 GetType() == WINDOW_GROUPBOX
)
1090 Window
* pSWindow
= NULL
;
1091 // get index, form start and form end
1092 USHORT nIndex
=0, nFormStart
=0, nFormEnd
=0;
1093 pSWindow
= ::ImplFindDlgCtrlWindow( pFrameWindow
,
1094 const_cast<Window
*>(this),
1100 // find the accelerated window
1101 pWindow
= ::ImplFindAccelWindow( pFrameWindow
,
1110 // find the next control; if that is a fixed text
1111 // fixed line or group box, then return NULL
1112 while( nIndex
< nFormEnd
)
1115 pSWindow
= ::ImplGetChildWindow( pFrameWindow
,
1119 if( pSWindow
&& pSWindow
->IsVisible() && ! (pSWindow
->GetStyle() & WB_NOLABEL
) )
1121 if( pSWindow
->GetType() != WINDOW_FIXEDTEXT
&&
1122 pSWindow
->GetType() != WINDOW_FIXEDLINE
&&
1123 pSWindow
->GetType() != WINDOW_GROUPBOX
)
1136 // -----------------------------------------------------------------------
1138 Window
* Window::GetLabeledBy() const
1140 if ( mpWindowImpl
->mbDisableAccessibleLabeledByRelation
)
1143 Window
* pWindow
= NULL
;
1144 Window
* pFrameWindow
= ImplGetFrameWindow();
1146 if ( mpWindowImpl
->mpRealParent
)
1147 pWindow
= mpWindowImpl
->mpRealParent
->GetParentLabeledBy( this );
1152 // #i62723#, #104191# checkboxes and radiobuttons are not supposed to have labels
1153 if( GetType() == WINDOW_CHECKBOX
|| GetType() == WINDOW_RADIOBUTTON
)
1156 if( ! ( GetType() == WINDOW_FIXEDTEXT
||
1157 GetType() == WINDOW_FIXEDLINE
||
1158 GetType() == WINDOW_GROUPBOX
) )
1160 // search for a control that labels this window
1161 // a label is considered the last fixed text, fixed line or group box
1162 // that comes before this control; with the exception of push buttons
1163 // which are labeled only if the fixed text, fixed line or group box
1164 // is directly before the control
1166 // get form start and form end and index of this control
1167 USHORT nIndex
, nFormStart
, nFormEnd
;
1168 Window
* pSWindow
= ::ImplFindDlgCtrlWindow( pFrameWindow
,
1169 const_cast<Window
*>(this),
1173 if( pSWindow
&& nIndex
!= nFormStart
)
1175 if( GetType() == WINDOW_PUSHBUTTON
||
1176 GetType() == WINDOW_HELPBUTTON
||
1177 GetType() == WINDOW_OKBUTTON
||
1178 GetType() == WINDOW_CANCELBUTTON
)
1180 nFormStart
= nIndex
-1;
1182 for( USHORT nSearchIndex
= nIndex
-1; nSearchIndex
>= nFormStart
; nSearchIndex
-- )
1184 USHORT nFoundIndex
= 0;
1185 pSWindow
= ::ImplGetChildWindow( pFrameWindow
,
1189 if( pSWindow
&& pSWindow
->IsVisible() &&
1190 ! (pSWindow
->GetStyle() & WB_NOLABEL
) &&
1191 ( pSWindow
->GetType() == WINDOW_FIXEDTEXT
||
1192 pSWindow
->GetType() == WINDOW_FIXEDLINE
||
1193 pSWindow
->GetType() == WINDOW_GROUPBOX
) )
1198 if( nFoundIndex
> nSearchIndex
|| nSearchIndex
== 0 )
1206 // -----------------------------------------------------------------------
1208 KeyEvent
Window::GetActivationKey() const
1212 sal_Unicode nAccel
= getAccel( GetText() );
1215 Window
* pWindow
= GetLabeledBy();
1217 nAccel
= getAccel( pWindow
->GetText() );
1222 if( nAccel
>= 'a' && nAccel
<= 'z' )
1223 nCode
= KEY_A
+ (nAccel
-'a');
1224 else if( nAccel
>= 'A' && nAccel
<= 'Z' )
1225 nCode
= KEY_A
+ (nAccel
-'A');
1226 else if( nAccel
>= '0' && nAccel
<= '9' )
1227 nCode
= KEY_0
+ (nAccel
-'0');
1228 KeyCode
aKeyCode( nCode
, FALSE
, FALSE
, TRUE
, FALSE
);
1229 aKeyEvent
= KeyEvent( nAccel
, aKeyCode
);