merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / window / dlgctrl.cxx
blobb70cc822f86f37af5aa1bfcdec9f865536cc83e6
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 $
10 * $Revision: 1.28 $
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;
68 if ( pResult )
70 while ( pResult->GetParent() && ( pResult->ImplGetWindow()->GetStyle() & WB_CHILDDLGCTRL ) )
71 pResult = pResult->GetParent();
74 return pResult;
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;
86 while ( 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
95 if ( pTabPage )
97 pFoundWindow = ImplGetSubChildWindow( pTabPage, n, nIndex );
98 pTabPage = NULL;
100 else
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
114 // existiert.
115 TabPage* pTempTabPage = pTabControl->GetTabPage( pTabControl->GetCurPageId() );
116 if ( pTempTabPage )
118 Window* pTempWindow = pTabControl->GetWindow( WINDOW_FIRSTCHILD );
119 while ( pTempWindow )
121 if ( pTempWindow->ImplGetWindow() == pTempTabPage )
123 pTabPage = pTempTabPage;
124 break;
126 pTempWindow = pTempWindow->GetWindow( WINDOW_NEXT );
130 else if ( ( pWindow->GetStyle() & WB_DIALOGCONTROL )
131 || ( pWindow->GetStyle() & WB_CHILDDLGCTRL ) )
132 pFoundWindow = ImplGetSubChildWindow( pWindow, n, nIndex );
135 if ( n == nIndex )
136 return pFoundWindow;
137 nIndex++;
140 if ( pTabPage )
141 pWindow = pTabPage;
142 else
144 pWindow = pNextWindow->GetWindow( WINDOW_NEXT );
145 pNextWindow = pWindow;
149 nIndex--;
150 return pFoundWindow;
153 // -----------------------------------------------------------------------
155 static Window* ImplGetChildWindow( Window* pParent, USHORT n, USHORT& nIndex, BOOL bTestEnable )
157 pParent = ImplGetTopParentOfTabHierarchy( pParent );
159 nIndex = 0;
160 Window* pWindow = ImplGetSubChildWindow( pParent, n, nIndex );
161 if ( bTestEnable )
163 USHORT n2 = nIndex;
164 while ( pWindow && (!pWindow->IsEnabled() || !pWindow->IsInputEnabled()) )
166 n2 = nIndex+1;
167 nIndex = 0;
168 pWindow = ImplGetSubChildWindow( pParent, n2, nIndex );
169 if ( nIndex < n2 )
170 break;
173 if ( (nIndex < n2) && n )
177 n--;
178 nIndex = 0;
179 pWindow = ImplGetSubChildWindow( pParent, n, nIndex );
181 while ( pWindow && n && (!pWindow->IsEnabled() || !pWindow->IsInputEnabled()) );
184 return pWindow;
187 // -----------------------------------------------------------------------
189 static Window* ImplGetNextWindow( Window* pParent, USHORT n, USHORT& nIndex, BOOL bTestEnable )
191 Window* pWindow = ImplGetChildWindow( pParent, n+1, nIndex, bTestEnable );
192 if ( n == nIndex )
194 n = 0;
195 pWindow = ImplGetChildWindow( pParent, n, nIndex, bTestEnable );
197 return pWindow;
200 // -----------------------------------------------------------------------
202 Window* Window::ImplGetDlgWindow( USHORT nIndex, USHORT nType,
203 USHORT nFormStart, USHORT nFormEnd,
204 USHORT* pIndex )
206 DBG_ASSERT( (nIndex >= nFormStart) && (nIndex <= nFormEnd),
207 "Window::ImplGetDlgWindow() - nIndex not in Form" );
209 Window* pWindow = NULL;
210 USHORT i;
211 USHORT nTemp;
212 USHORT nStartIndex;
214 if ( nType == DLGWINDOW_PREV )
216 i = nIndex;
219 if ( i > nFormStart )
220 i--;
221 else
222 i = nFormEnd;
223 pWindow = ImplGetChildWindow( this, i, nTemp, TRUE );
224 if ( !pWindow )
225 break;
226 if ( (i == nTemp) && (pWindow->GetStyle() & WB_TABSTOP) )
227 break;
229 while ( i != nIndex );
231 else
233 i = nIndex;
234 pWindow = ImplGetChildWindow( this, i, i, (nType == DLGWINDOW_FIRST) );
235 if ( pWindow )
237 nStartIndex = i;
239 if ( nType == DLGWINDOW_NEXT )
241 if ( i < nFormEnd )
243 pWindow = ImplGetNextWindow( this, i, i, TRUE );
244 if ( (i > nFormEnd) || (i < nFormStart) )
245 pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
247 else
248 pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
251 if ( i <= nFormEnd )
253 // 2ten Index mitfuehren, falls alle Controls disablte
254 USHORT nStartIndex2 = i;
255 USHORT nOldIndex = i+1;
259 if ( pWindow->GetStyle() & WB_TABSTOP )
260 break;
261 if( i == nOldIndex ) // only disabled controls ?
263 i = nStartIndex2;
264 break;
266 nOldIndex = i;
267 if ( (i > nFormEnd) || (i < nFormStart) )
268 pWindow = ImplGetChildWindow( this, nFormStart, i, TRUE );
269 else
270 pWindow = ImplGetNextWindow( this, i, i, TRUE );
272 while ( (i != nStartIndex) && (i != nStartIndex2) );
274 if ( (i == nStartIndex2) &&
275 (!(pWindow->GetStyle() & WB_TABSTOP) || !pWindow->IsEnabled()) )
276 i = nStartIndex;
280 if ( nType == DLGWINDOW_FIRST )
282 if ( pWindow )
284 if ( pWindow->GetType() == WINDOW_TABCONTROL )
286 Window* pNextWindow = ImplGetDlgWindow( i, DLGWINDOW_NEXT );
287 if ( pNextWindow )
289 if ( pWindow->IsChild( pNextWindow ) )
290 pWindow = pNextWindow;
294 if ( !(pWindow->GetStyle() & WB_TABSTOP) )
295 pWindow = NULL;
300 if ( pIndex )
301 *pIndex = i;
303 return pWindow;
306 // -----------------------------------------------------------------------
308 static Window* ImplFindDlgCtrlWindow( Window* pParent, Window* pWindow, USHORT& rIndex,
309 USHORT& rFormStart, USHORT& rFormEnd )
311 Window* pSWindow;
312 Window* pSecondWindow = NULL;
313 Window* pTempWindow = NULL;
314 USHORT i;
315 USHORT nSecond_i = 0;
316 USHORT nFormStart = 0;
317 USHORT nSecondFormStart = 0;
318 USHORT nFormEnd;
320 // Focus-Fenster in der Child-Liste suchen
321 Window* pFirstChildWindow = pSWindow = ImplGetChildWindow( pParent, 0, i, FALSE );
323 if( pWindow == NULL )
324 pWindow = pSWindow;
326 while ( pSWindow )
328 // the DialogControlStart mark is only accepted for the direct children
329 if ( !ImplHasIndirectTabParent( pSWindow )
330 && pSWindow->ImplGetWindow()->IsDialogControlStart() )
331 nFormStart = i;
333 // SecondWindow wegen zusammengesetzten Controls wie
334 // ComboBoxen und Feldern
335 if ( pSWindow->ImplIsWindowOrChild( pWindow ) )
337 pSecondWindow = pSWindow;
338 nSecond_i = i;
339 nSecondFormStart = nFormStart;
340 if ( pSWindow == pWindow )
341 break;
344 pSWindow = ImplGetNextWindow( pParent, i, i, FALSE );
345 if ( !i )
346 pSWindow = NULL;
349 if ( !pSWindow )
351 // Fenster nicht gefunden, dann koennen wir auch keine
352 // Steuerung uebernehmen
353 if ( !pSecondWindow )
354 return NULL;
355 else
357 pSWindow = pSecondWindow;
358 i = nSecond_i;
359 nFormStart = nSecondFormStart;
363 // Start-Daten setzen
364 rIndex = i;
365 rFormStart = nFormStart;
367 // Formularende suchen
368 nFormEnd = nFormStart;
369 pTempWindow = pSWindow;
370 sal_Int32 nIteration = 0;
373 nFormEnd = i;
374 pTempWindow = ImplGetNextWindow( pParent, i, i, FALSE );
376 // the DialogControlStart mark is only accepted for the direct children
377 if ( !i
378 || ( pTempWindow && !ImplHasIndirectTabParent( pTempWindow )
379 && pTempWindow->ImplGetWindow()->IsDialogControlStart() ) )
380 break;
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...
388 nIteration++;
389 if ( nIteration >= 2 )
391 // this is an unexpected scenario
392 DBG_ASSERT( FALSE, "It seems to be an endless loop!" );
393 rFormStart = 0;
394 break;
398 while ( pTempWindow );
399 rFormEnd = nFormEnd;
401 return pSWindow;
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;
414 USHORT i = rIndex;
415 int bSearch = TRUE;
416 Window* pWindow;
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];
426 if ( i < nFormEnd )
427 pWindow = ImplGetNextWindow( pParent, i, i, TRUE );
428 else
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 );
445 rIndex = i;
446 return pWindow;
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 )
457 USHORT nChildIndex;
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,
466 bCheckEnable );
467 if( pAccelWin )
468 return pAccelWin;
471 if ( i == nStart )
472 break;
474 if ( i < nFormEnd )
476 pWindow = ImplGetNextWindow( pParent, i, i, bCheckEnable );
477 if( ! pWindow )
478 pWindow = ImplGetChildWindow( pParent, nFormStart, i, bCheckEnable );
480 else
481 pWindow = ImplGetChildWindow( pParent, nFormStart, i, bCheckEnable );
484 return NULL;
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 );
497 else
498 ImplGrabFocus( nFlags );
500 else
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();
516 else
518 if ( GetType() == WINDOW_RADIOBUTTON )
520 if ( !((RadioButton*)this)->IsChecked() )
521 ((RadioButton*)this)->ImplCallClick( TRUE, nFlags );
522 else
523 ImplGrabFocus( nFlags );
525 else
526 ImplGrabFocus( nFlags );
530 // -----------------------------------------------------------------------
532 BOOL Window::ImplDlgCtrl( const KeyEvent& rKEvt, BOOL bKeyInput )
534 KeyCode aKeyCode = rKEvt.GetKeyCode();
535 USHORT nKeyCode = aKeyCode.GetCode();
536 Window* pSWindow;
537 Window* pTempWindow;
538 Window* pButtonWindow;
539 USHORT i;
540 USHORT iButton;
541 USHORT iButtonStart;
542 USHORT iTemp;
543 USHORT nIndex;
544 USHORT nFormStart;
545 USHORT nFormEnd;
546 USHORT nDlgCtrlFlags;
548 // Ohne Focus-Window koennen wir auch keine Steuerung uebernehmen
549 Window* pFocusWindow = Application::GetFocusWindow();
550 if ( !pFocusWindow || !ImplIsWindowOrChild( pFocusWindow ) )
551 return FALSE;
553 // Focus-Fenster in der Child-Liste suchen
554 pSWindow = ::ImplFindDlgCtrlWindow( this, pFocusWindow,
555 nIndex, nFormStart, nFormEnd );
556 if ( !pSWindow )
557 return FALSE;
558 i = nIndex;
560 nDlgCtrlFlags = 0;
561 pTempWindow = pSWindow;
564 nDlgCtrlFlags |= pTempWindow->GetDialogControlFlags();
565 if ( pTempWindow == this )
566 break;
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 )
582 break;
584 pButtonWindow = ImplGetNextWindow( this, iButton, iButton, TRUE );
585 if ( (iButton <= iButtonStart) || (iButton > nFormEnd) )
586 pButtonWindow = NULL;
589 if ( bKeyInput && !pButtonWindow && (nDlgCtrlFlags & WINDOW_DLGCTRL_RETURN) )
591 USHORT nType;
592 USHORT nGetFocusFlags = GETFOCUS_TAB;
593 USHORT nNewIndex;
594 USHORT iStart;
595 if ( aKeyCode.IsShift() )
597 nType = DLGWINDOW_PREV;
598 nGetFocusFlags |= GETFOCUS_BACKWARD;
600 else
602 nType = DLGWINDOW_NEXT;
603 nGetFocusFlags |= GETFOCUS_FORWARD;
605 iStart = i;
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;
617 else
619 if ( nNewIndex < iStart )
620 nGetFocusFlags |= GETFOCUS_AROUND;
622 pTempWindow->ImplControlFocus( nGetFocusFlags );
623 return TRUE;
625 else
627 i = nNewIndex;
628 pTempWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
630 if ( (i <= iStart) || (i > nFormEnd) )
631 pTempWindow = NULL;
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;
645 return TRUE;
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 )
657 break;
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;
670 return TRUE;
674 else if ( bKeyInput )
676 if ( nKeyCode == KEY_TAB )
678 // keine Alt-Taste abfangen, wegen Windows
679 if ( !aKeyCode.IsMod2() )
681 USHORT nType;
682 USHORT nGetFocusFlags = GETFOCUS_TAB;
683 USHORT nNewIndex;
684 BOOL bFormular = FALSE;
686 // Bei Ctrl-Tab erstmal testen, ob zwischen Formularen
687 // gesprungen werden soll
688 if ( aKeyCode.IsMod1() )
690 // Gruppe suchen
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() )
700 if ( iTemp != 0 )
701 bFormular = TRUE;
702 if ( aKeyCode.IsShift() )
704 if ( iTemp <= nIndex )
705 pFormularFirstWindow = pPrevFirstFormularFirstWindow;
706 pPrevFirstFormularFirstWindow = pTempWindow;
708 else
710 if ( (iTemp > nIndex) && !pFormularFirstWindow )
711 pFormularFirstWindow = pTempWindow;
713 pLastFormularFirstWindow = pTempWindow;
716 pTempWindow = ImplGetNextWindow( this, iTemp, iTemp, FALSE );
717 if ( !iTemp )
718 pTempWindow = NULL;
721 if ( bFormular )
723 if ( !pFormularFirstWindow )
725 if ( aKeyCode.IsShift() )
726 pFormularFirstWindow = pLastFormularFirstWindow;
727 else
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();
742 return TRUE;
748 if ( !bFormular )
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;
760 else
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;
778 return TRUE;
780 else if ( pWindow )
782 // Around-Flag ermitteln
783 if ( nType == DLGWINDOW_PREV )
785 if ( nNewIndex > i )
786 nGetFocusFlags |= GETFOCUS_AROUND;
788 else
790 if ( nNewIndex < i )
791 nGetFocusFlags |= GETFOCUS_AROUND;
793 pWindow->ImplControlFocus( nGetFocusFlags );
794 return TRUE;
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 );
807 while ( pWindow )
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 );
817 return TRUE;
820 if ( nStyle & WB_GROUP )
821 break;
823 pWindow = pWindow->GetWindow( WINDOW_PREV );
827 else if ( (nKeyCode == KEY_RIGHT) || (nKeyCode == KEY_DOWN) )
829 Window* pWindow;
830 WinBits nStyle;
831 pWindow = pSWindow->GetWindow( WINDOW_NEXT );
832 while ( pWindow )
834 pWindow = pWindow->ImplGetWindow();
836 nStyle = pWindow->GetStyle();
838 if ( nStyle & WB_GROUP )
839 break;
841 if ( pWindow->IsVisible() && pWindow->IsEnabled() && pWindow->IsInputEnabled() )
843 pWindow->ImplControlFocus( GETFOCUS_CURSOR | GETFOCUS_BACKWARD );
844 return TRUE;
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();
855 if ( c )
857 pSWindow = ::ImplFindAccelWindow( this, i, c, nFormStart, nFormEnd );
858 if ( pSWindow )
860 USHORT nGetFocusFlags = GETFOCUS_MNEMONIC;
861 if ( pSWindow == ::ImplFindAccelWindow( this, i, c, nFormStart, nFormEnd ) )
862 nGetFocusFlags |= GETFOCUS_UNIQUEMNEMONIC;
863 pSWindow->ImplControlFocus( nGetFocusFlags );
864 return TRUE;
870 if ( pButtonWindow && pButtonWindow->IsVisible() && pButtonWindow->IsEnabled() && pButtonWindow->IsInputEnabled() )
872 if ( bKeyInput )
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();
890 return TRUE;
893 return FALSE;
896 // -----------------------------------------------------------------------
898 // checks if this window has dialog control
899 BOOL Window::ImplHasDlgCtrl()
901 Window* pDlgCtrlParent;
902 Window* pDlgCtrl;
904 // lookup window for dialog control
905 pDlgCtrl = this;
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) )
913 return FALSE;
914 else
915 return TRUE;
918 void Window::ImplDlgCtrlNextWindow()
920 Window* pDlgCtrlParent;
921 Window* pDlgCtrl;
922 Window* pSWindow;
923 USHORT nIndex;
924 USHORT nFormStart;
925 USHORT nFormEnd;
927 // lookup window for dialog control
928 pDlgCtrl = this;
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) )
936 return;
938 // lookup window in child list
939 pSWindow = ::ImplFindDlgCtrlWindow( pDlgCtrlParent, pDlgCtrl,
940 nIndex, nFormStart, nFormEnd );
941 if ( !pSWindow )
942 return;
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,
952 BOOL bGetFocus )
954 PushButton* pOldDefButton = NULL;
955 PushButton* pNewDefButton = NULL;
956 Window* pSWindow;
957 USHORT i;
958 USHORT nFormStart;
959 USHORT nFormEnd;
961 // Formular suchen
962 pSWindow = ::ImplFindDlgCtrlWindow( pParent, pFocusWindow, i, nFormStart, nFormEnd );
963 if ( !pSWindow )
965 nFormStart = 0;
966 nFormEnd = 0xFFFF;
969 pSWindow = ImplGetChildWindow( pParent, nFormStart, i, FALSE );
970 while ( pSWindow )
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) )
985 pSWindow = NULL;
988 if ( !bGetFocus )
990 USHORT nDummy;
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 )
1025 USHORT nIndex;
1026 USHORT nFormStart;
1027 USHORT nFormEnd;
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
1038 return NULL;
1041 // -----------------------------------------------------------------------
1043 Window* Window::GetParentLabeledBy( const Window* ) const
1045 return NULL;
1048 // -----------------------------------------------------------------------
1050 static sal_Unicode getAccel( const String& rStr )
1052 sal_Unicode nChar = 0;
1053 USHORT nPos = 0;
1056 nPos = rStr.Search( '~', nPos );
1057 if( nPos != STRING_NOTFOUND && nPos < rStr.Len() )
1058 nChar = rStr.GetChar( ++nPos );
1059 else
1060 nChar = 0;
1061 } while( nChar == '~' );
1062 return nChar;
1065 Window* Window::GetLabelFor() const
1067 if ( mpWindowImpl->mbDisableAccessibleLabelForRelation )
1068 return NULL;
1070 Window* pWindow = NULL;
1071 Window* pFrameWindow = ImplGetFrameWindow();
1073 WinBits nFrameStyle = pFrameWindow->GetStyle();
1074 if( ! ( nFrameStyle & WB_DIALOGCONTROL )
1075 || ( nFrameStyle & WB_NODIALOGCONTROL )
1077 return NULL;
1079 if ( mpWindowImpl->mpRealParent )
1080 pWindow = mpWindowImpl->mpRealParent->GetParentLabelFor( this );
1082 if( pWindow )
1083 return pWindow;
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),
1095 nIndex,
1096 nFormStart,
1097 nFormEnd );
1098 if( nAccel )
1100 // find the accelerated window
1101 pWindow = ::ImplFindAccelWindow( pFrameWindow,
1102 nIndex,
1103 nAccel,
1104 nFormStart,
1105 nFormEnd,
1106 FALSE );
1108 else
1110 // find the next control; if that is a fixed text
1111 // fixed line or group box, then return NULL
1112 while( nIndex < nFormEnd )
1114 nIndex++;
1115 pSWindow = ::ImplGetChildWindow( pFrameWindow,
1116 nIndex,
1117 nIndex,
1118 FALSE );
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 )
1125 pWindow = pSWindow;
1127 break;
1133 return pWindow;
1136 // -----------------------------------------------------------------------
1138 Window* Window::GetLabeledBy() const
1140 if ( mpWindowImpl->mbDisableAccessibleLabeledByRelation )
1141 return NULL;
1143 Window* pWindow = NULL;
1144 Window* pFrameWindow = ImplGetFrameWindow();
1146 if ( mpWindowImpl->mpRealParent )
1147 pWindow = mpWindowImpl->mpRealParent->GetParentLabeledBy( this );
1149 if( pWindow )
1150 return pWindow;
1152 // #i62723#, #104191# checkboxes and radiobuttons are not supposed to have labels
1153 if( GetType() == WINDOW_CHECKBOX || GetType() == WINDOW_RADIOBUTTON )
1154 return NULL;
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),
1170 nIndex,
1171 nFormStart,
1172 nFormEnd );
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,
1186 nSearchIndex,
1187 nFoundIndex,
1188 FALSE );
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 ) )
1195 pWindow = pSWindow;
1196 break;
1198 if( nFoundIndex > nSearchIndex || nSearchIndex == 0 )
1199 break;
1203 return pWindow;
1206 // -----------------------------------------------------------------------
1208 KeyEvent Window::GetActivationKey() const
1210 KeyEvent aKeyEvent;
1212 sal_Unicode nAccel = getAccel( GetText() );
1213 if( ! nAccel )
1215 Window* pWindow = GetLabeledBy();
1216 if( pWindow )
1217 nAccel = getAccel( pWindow->GetText() );
1219 if( nAccel )
1221 USHORT nCode = 0;
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 );
1231 return aKeyEvent;