Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/vcl/source/window/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 40 kB image not shown  

Quelle  dlgctrl.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */



#include <svdata.hxx>
#include <window.h>

#include "dlgctrl.hxx"
#include <vcl/event.hxx>
#include <vcl/toolkit/fixed.hxx>
#include <vcl/layout.hxx>
#include <vcl/svapp.hxx>
#include <vcl/tabpage.hxx>
#include <vcl/tabctrl.hxx>
#include <vcl/toolkit/button.hxx>
#include <vcl/toolbox.hxx>
#include <vcl/settings.hxx>
#include <sal/log.hxx>
#include <i18nlangtag/languagetag.hxx>

#include <com/sun/star/i18n/XCharacterClassification.hpp>

using namespace ::com::sun::star;

static bool ImplHasIndirectTabParent( vcl::Window* pWindow )
{
    // The window has indirect tab parent if it is included in tab hierarchy
    // of the indirect parent window

    vcl::Window* pNonLayoutParent = getNonLayoutParent(pWindow);
    return ( pNonLayoutParent
          && ( pNonLayoutParent->ImplGetWindow()->GetStyle() & WB_CHILDDLGCTRL ) );
}

static vcl::Window* ImplGetTopParentOfTabHierarchy( vcl::Window* pParent )
{
    // The method allows to find the most close parent containing all the
    // window from the current tab-hierarchy
    // The direct parent should be provided as a parameter here

    vcl::Window* pResult = pParent;

    if ( pResult )
    {
        vcl::Window* pNonLayoutParent = getNonLayoutParent(pResult);
        while ( pNonLayoutParent && ( pResult->ImplGetWindow()->GetStyle() & WB_CHILDDLGCTRL ) )
        {
            pResult = pNonLayoutParent;
            pNonLayoutParent = getNonLayoutParent(pResult);
        }
    }

    return pResult;
}

static vcl::Window* ImplGetCurTabWindow(const vcl::Window* pWindow)
{
    assert(pWindow->GetType() == WindowType::TABCONTROL);
    const TabControl* pTabControl = static_cast<const TabControl*>(pWindow);
    // Check if the TabPage is a Child of the TabControl and still exists (by
    // walking all child windows); because it could be that the TabPage has been
    // destroyed already by a Dialog-Dtor, event that the TabControl still exists.
    TabPage* pTempTabPage = pTabControl->GetTabPage(pTabControl->GetCurPageId());
    if (pTempTabPage)
    {
        vcl::Window* pTempWindow = pTabControl->GetWindow(GetWindowType::FirstChild);
        while (pTempWindow)
        {
            if (pTempWindow->ImplGetWindow() == pTempTabPage)
            {
                return pTempTabPage;
            }
            pTempWindow = nextLogicalChildOfParent(pTabControl, pTempWindow);
        }
    }

    return nullptr;
}

static vcl::Window* ImplGetSubChildWindow( vcl::Window* pParent, sal_uInt16 n, sal_uInt16& nIndex )
{
    // ignore all windows with mpClientWindow set
    for (vcl::Window *pNewParent = pParent->ImplGetWindow();
         pParent != pNewParent; pParent = pNewParent);

    vcl::Window* pFoundWindow = nullptr;
    vcl::Window* pWindow = firstLogicalChildOfParent(pParent);
    vcl::Window* pNextWindow = pWindow;

    // process just the current page of a tab control
    if (pWindow && pParent->GetType() == WindowType::TABCONTROL)
    {
        pWindow = ImplGetCurTabWindow(pParent);
        pNextWindow = lastLogicalChildOfParent(pParent);
    }

    while (pWindow)
    {
        pWindow = pWindow->ImplGetWindow();

        // skip invisible and disabled windows
        if (isVisibleInLayout(pWindow))
        {
            // return the TabControl itself, before handling its page
            if (pWindow->GetType() == WindowType::TABCONTROL)
            {
                if (n == nIndex)
                    return pWindow;
                ++nIndex;
            }
            if (pWindow->GetStyle() & (WB_DIALOGCONTROL | WB_CHILDDLGCTRL))
                pFoundWindow = ImplGetSubChildWindow(pWindow, n, nIndex);
            else
                pFoundWindow = pWindow;

            if (n == nIndex)
                return pFoundWindow;
            ++nIndex;
        }

        pWindow = nextLogicalChildOfParent(pParent, pNextWindow);
        pNextWindow = pWindow;
    }

    --nIndex;
    assert(!pFoundWindow || (pFoundWindow == pFoundWindow->ImplGetWindow()));
    return pFoundWindow;
}

vcl::Window* ImplGetChildWindow( vcl::Window* pParent, sal_uInt16 n, sal_uInt16& nIndex, bool bTestEnable )
{
    pParent = ImplGetTopParentOfTabHierarchy( pParent );

    nIndex = 0;
    vcl::Window* pWindow = ImplGetSubChildWindow( pParent, n, nIndex );
    if ( bTestEnable )
    {
        sal_uInt16 n2 = nIndex;
        while ( pWindow && (!isEnabledInLayout(pWindow) || !pWindow->IsInputEnabled()) )
        {
            n2 = nIndex+1;
            nIndex = 0;
            pWindow = ImplGetSubChildWindow( pParent, n2, nIndex );
            if ( nIndex < n2 )
                break;
        }

        if ( (nIndex < n2) && n )
        {
            do
            {
                n--;
                nIndex = 0;
                pWindow = ImplGetSubChildWindow( pParent, n, nIndex );
            }
            while ( pWindow && n && (!isEnabledInLayout(pWindow) || !pWindow->IsInputEnabled()) );
        }
    }
    return pWindow;
}

static vcl::Window* ImplGetNextWindow( vcl::Window* pParent, sal_uInt16 n, sal_uInt16&&nbsp;nIndex, bool bTestEnable )
{
    vcl::Window* pWindow = ImplGetChildWindow( pParent, n+1, nIndex, bTestEnable );
    if ( n == nIndex )
    {
        n = 0;
        pWindow = ImplGetChildWindow( pParent, n, nIndex, bTestEnable );
    }
    return pWindow;
}

namespace vcl {

static bool lcl_ToolBoxTabStop( Window* pWindow )
{
    ToolBox* pToolBoxWindow = static_cast<ToolBox*>( pWindow );

    for ( ToolBox::ImplToolItems::size_type nPos = 0; nPos < pToolBoxWindow->GetItemCount(); nPos++ )
    {
        ToolBoxItemId nId = pToolBoxWindow->GetItemId( nPos );
        if ( pToolBoxWindow->IsItemVisible( nId ) && pToolBoxWindow->IsItemEnabled( nId ) )
            return true;
    }

    return false;
}

vcl::Window* Window::ImplGetDlgWindow( sal_uInt16 nIndex, GetDlgWindowType nType,
                                  sal_uInt16 nFormStart, sal_uInt16 nFormEnd,
                                  sal_uInt16* pIndex )
{
    SAL_WARN_IF( (nIndex < nFormStart) || (nIndex > nFormEnd), "vcl",
                "Window::ImplGetDlgWindow() - nIndex not in Form" );

    vcl::Window* pWindow = nullptr;
    sal_uInt16  i;
    sal_uInt16  nTemp;
    sal_uInt16  nStartIndex;

    if ( nType == GetDlgWindowType::Prev )
    {
        i = nIndex;
        do
        {
            if ( i > nFormStart )
                i--;
            else
                i = nFormEnd;
            pWindow = ImplGetChildWindow( this, i, nTemp, true );
            if ( !pWindow )
                break;
            if ( (i == nTemp) && (pWindow->GetStyle() & WB_TABSTOP) )
            {
                if ( WindowType::TOOLBOX == pWindow->GetType() )
                {
                    if ( lcl_ToolBoxTabStop( pWindow ) )
                        break;
                }
                else
                    break;
            }
        }
        while ( i != nIndex );
    }
    else
    {
        i = nIndex;
        pWindow = ImplGetChildWindow( this, i, i, (nType == GetDlgWindowType::First) );
        if ( pWindow )
        {
            nStartIndex = i;

            if ( nType == GetDlgWindowType::Next )
            {
                if ( i < nFormEnd )
                {
                    pWindow = ImplGetNextWindow( this, i, i, true );
                    if ( (i > nFormEnd) || (i < nFormStart) )
                        pWindow = ImplGetChildWindow( this, nFormStart, i, true );
                }
                else
                    pWindow = ImplGetChildWindow( this, nFormStart, i, true );
            }

            if (i <= nFormEnd && pWindow)
            {
                // carry the 2nd index, in case all controls are disabled
                sal_uInt16 nStartIndex2 = i;
                sal_uInt16 nOldIndex = i+1;

                do
                {
                    if ( pWindow->GetStyle() & WB_TABSTOP )
                    {
                        if ( WindowType::TOOLBOX == pWindow->GetType() )
                        {
                            if ( lcl_ToolBoxTabStop( pWindow ) )
                                break;
                        }
                        else
                            break;
                    }
                    if( i == nOldIndex ) // only disabled controls ?
                    {
                        i = nStartIndex2;
                        break;
                    }
                    nOldIndex = i;
                    if ( (i > nFormEnd) || (i < nFormStart) )
                        pWindow = ImplGetChildWindow( this, nFormStart, i, true );
                    else
                        pWindow = ImplGetNextWindow( this, i, i, true );
                }
                while (i != nStartIndex && i != nStartIndex2 && pWindow);

                if ( (i == nStartIndex2) && pWindow &&
                     (!(pWindow->GetStyle() & WB_TABSTOP) || !isEnabledInLayout(pWindow)) )
                    i = nStartIndex;
            }
        }

        if ( nType == GetDlgWindowType::First )
        {
            if ( pWindow )
            {
                if ( pWindow->GetType() == WindowType::TABCONTROL )
                {
                    vcl::Window* pNextWindow = ImplGetDlgWindow( i, GetDlgWindowType::Next );
                    if ( pNextWindow )
                    {
                        if ( pWindow->IsChild( pNextWindow ) )
                            pWindow = pNextWindow;
                    }
                }

                if ( !(pWindow->GetStyle() & WB_TABSTOP) )
                    pWindow = nullptr;
            }
        }
    }

    if ( pIndex )
        *pIndex = i;

    return pWindow;
}

/* namespace vcl */

vcl::Window* ImplFindDlgCtrlWindow(vcl::Window* pParent, const vcl::Window* pWindow,
                                   sal_uInt16& rIndex, sal_uInt16& rFormStart, sal_uInt16& rFormEnd)
{
    vcl::Window* pSWindow;
    vcl::Window* pSecondWindow = nullptr;
    vcl::Window* pTempWindow = nullptr;
    sal_uInt16  i;
    sal_uInt16  nSecond_i = 0;
    sal_uInt16  nFormStart = 0;
    sal_uInt16  nSecondFormStart = 0;
    sal_uInt16  nFormEnd;

    // find focus window in the child list
    vcl::Window* pFirstChildWindow = pSWindow = ImplGetChildWindow( pParent, 0, i, false );

    if( pWindow == nullptr )
        pWindow = pSWindow;

    while ( pSWindow )
    {
        // the DialogControlStart mark is only accepted for the direct children
        if ( !ImplHasIndirectTabParent( pSWindow )
          && pSWindow->ImplGetWindow()->IsDialogControlStart() )
            nFormStart = i;

        // SecondWindow for composite controls like ComboBoxes and arrays
        if ( pSWindow->ImplIsWindowOrChild( pWindow ) )
        {
            pSecondWindow = pSWindow;
            nSecond_i = i;
            nSecondFormStart = nFormStart;
            if ( pSWindow == pWindow )
                break;
        }

        pSWindow = ImplGetNextWindow( pParent, i, i, false );
        if ( !i )
            pSWindow = nullptr;
    }

    if ( !pSWindow )
    {
        // Window not found; we cannot handle it
        if ( !pSecondWindow )
            return nullptr;
        else
        {
            pSWindow = pSecondWindow;
            i = nSecond_i;
            nFormStart = nSecondFormStart;
        }
    }

    // initialize
    rIndex = i;
    rFormStart = nFormStart;

    // find end of template
    sal_Int32 nIteration = 0;
    do
    {
        nFormEnd = i;
        pTempWindow = ImplGetNextWindow( pParent, i, i, false );

        // the DialogControlStart mark is only accepted for the direct children
        if ( !i
          || ( pTempWindow && !ImplHasIndirectTabParent( pTempWindow )
               && pTempWindow->ImplGetWindow()->IsDialogControlStart() ) )
            break;

        if ( pTempWindow && pTempWindow == pFirstChildWindow )
        {
            // It is possible to go through the begin of hierarchy once
            // while looking for DialogControlStart mark.
            // If it happens second time, it looks like an endless loop,
            // that should be impossible, but just for the case...
            nIteration++;
            if ( nIteration >= 2 )
            {
                // this is an unexpected scenario
                SAL_WARN( "vcl""It seems to be an endless loop!" );
                rFormStart = 0;
                break;
            }
        }
    }
    while ( pTempWindow );
    rFormEnd = nFormEnd;

    return pSWindow;
}

vcl::Window* ImplFindAccelWindow( vcl::Window* pParent, sal_uInt16& rIndex, sal_Unicode cCharCode,
                             sal_uInt16 nFormStart, sal_uInt16 nFormEnd, bool bCheckEnable )
{
    SAL_WARN_IF( (rIndex < nFormStart) || (rIndex > nFormEnd), "vcl",
                "Window::ImplFindAccelWindow() - rIndex not in Form" );

    sal_Unicode cCompareChar;
    sal_uInt16  nStart = rIndex;
    sal_uInt16  i = rIndex;
    vcl::Window* pWindow;

    uno::Reference<i18n::XCharacterClassification> const& xCharClass(ImplGetCharClass());

    const css::lang::Locale& rLocale = Application::GetSettings().GetUILanguageTag().getLocale();
    cCharCode = xCharClass->toUpper( OUString(cCharCode), 0, 1, rLocale )[0];

    if ( i < nFormEnd )
        pWindow = ImplGetNextWindow( pParent, i, i, true );
    else
        pWindow = ImplGetChildWindow( pParent, nFormStart, i, true );
    while( pWindow )
    {
        const OUString aStr = pWindow->GetText();
        sal_Int32 nPos = aStr.indexOf( '~' );
        while (nPos != -1)
        {
            cCompareChar = aStr[nPos+1];
            cCompareChar = xCharClass->toUpper( OUString(cCompareChar), 0, 1, rLocale )[0];
            if ( cCompareChar == cCharCode )
            {
                if (pWindow->GetType() == WindowType::FIXEDTEXT)
                {
                    FixedText *pFixedText = static_cast<FixedText*>(pWindow);
                    vcl::Window *pMnemonicWidget = pFixedText->get_mnemonic_widget();
                    SAL_WARN_IF(isContainerWindow(pFixedText->GetParent()) && !pMnemonicWidget,
                        "vcl.a11y""label missing mnemonic_widget?");
                    if (pMnemonicWidget)
                        return pMnemonicWidget;
                }

                // skip Static-Controls
                if ( (pWindow->GetType() == WindowType::FIXEDTEXT)   ||
                     (pWindow->GetType() == WindowType::FIXEDLINE)   ||
                     (pWindow->GetType() == WindowType::GROUPBOX) )
                    pWindow = pParent->ImplGetDlgWindow( i, GetDlgWindowType::Next );
                rIndex = i;
                return pWindow;
            }
            nPos = aStr.indexOf( '~', nPos+1 );
        }

        // #i93011# it would have made sense to have this really recursive
        // right from the start. However this would cause unpredictable side effects now
        // so instead we have a style bit for some child windows, that want their
        // children checked for accelerators
        if( (pWindow->GetStyle() & WB_CHILDDLGCTRL) != 0 )
        {
            sal_uInt16  nChildIndex;
            sal_uInt16  nChildFormStart;
            sal_uInt16  nChildFormEnd;

            // get form start and end
            ::ImplFindDlgCtrlWindow( pWindow, nullptr,
                                     nChildIndex, nChildFormStart, nChildFormEnd );
            vcl::Window* pAccelWin = ImplFindAccelWindow( pWindow, nChildIndex, cCharCode,
                                                     nChildFormStart, nChildFormEnd,
                                                     bCheckEnable );
            if( pAccelWin )
                return pAccelWin;
        }

        if ( i == nStart )
            break;

        if ( i < nFormEnd )
        {
            pWindow = ImplGetNextWindow( pParent, i, i, bCheckEnable );
            if( ! pWindow )
                pWindow = ImplGetChildWindow( pParent, nFormStart, i, bCheckEnable );
        }
        else
            pWindow = ImplGetChildWindow( pParent, nFormStart, i, bCheckEnable );
    }

    return nullptr;
}

namespace vcl {

void Window::SetMnemonicActivateHdl(const Link<vcl::Window&, bool>& rLink)
{
    if (mpWindowImpl) // may be called after dispose
    {
        mpWindowImpl->maMnemonicActivateHdl = rLink;
    }
}

void Window::ImplControlFocus( GetFocusFlags nFlags )
{
    if ( nFlags & GetFocusFlags::Mnemonic )
    {
        if (mpWindowImpl->maMnemonicActivateHdl.Call(*this))
            return;

        const bool bUniqueMnemonic(nFlags & GetFocusFlags::UniqueMnemonic);

        if ( GetType() == WindowType::RADIOBUTTON )
        {
            if (bUniqueMnemonic && !static_cast<RadioButton*>(this)->IsChecked())
                static_cast<RadioButton*>(this)->ImplCallClick( true, nFlags );
            else
                ImplGrabFocus( nFlags );
        }
        else
        {
            ImplGrabFocus( nFlags );
            if (bUniqueMnemonic)
            {
                if ( GetType() == WindowType::CHECKBOX )
                    static_cast<CheckBox*>(this)->ImplCheck();
                else if ( mpWindowImpl->mbPushButton )
                {
                    static_cast<PushButton*>(this)->SetPressed( true );
                    static_cast<PushButton*>(this)->SetPressed( false );
                    static_cast<PushButton*>(this)->Click();
                }
            }
        }
    }
    else
    {
        if ( GetType() == WindowType::RADIOBUTTON )
        {
            if ( !static_cast<RadioButton*>(this)->IsChecked() )
                static_cast<RadioButton*>(this)->ImplCallClick( true, nFlags );
            else
                ImplGrabFocus( nFlags );
        }
        else
            ImplGrabFocus( nFlags );
    }
}

/* namespace vcl */

namespace
{
    bool isSuitableDestination(vcl::Window const *pWindow)
    {
        return (pWindow && isVisibleInLayout(pWindow) &&
                isEnabledInLayout(pWindow) && pWindow->IsInputEnabled() &&
                //Pure window shouldn't get window after controls such as
                //buttons.
                (pWindow->GetType() != WindowType::WINDOW &&
                  pWindow->GetType() != WindowType::WORKWINDOW && pWindow->GetType() != WindowType::CONTROL)
               );
    }

    bool focusNextInGroup(const std::vector<VclPtr<RadioButton> >::iterator& aStart, std::vector<VclPtr<RadioButton> > &rGroup)
    {
        std::vector<VclPtr<RadioButton> >::iterator aI(aStart);

        if (aStart != rGroup.end())
            ++aI;

        aI = std::find_if(aI, rGroup.end(), isSuitableDestination);
        if (aI != rGroup.end())
        {
            vcl::Window *pWindow = *aI;
            pWindow->ImplControlFocus( GetFocusFlags::CURSOR | GetFocusFlags::Forward );
            return true;
        }
        aI = std::find_if(rGroup.begin(), aStart, isSuitableDestination);
        if (aI != aStart)
        {
            vcl::Window *pWindow = *aI;
            pWindow->ImplControlFocus( GetFocusFlags::CURSOR | GetFocusFlags::Forward );
            return true;
        }
        return false;
    }

    bool nextInGroup(RadioButton *pSourceWindow, bool bBackward)
    {
        std::vector<VclPtr<RadioButton> > aGroup(pSourceWindow->GetRadioButtonGroup());

        if (aGroup.size() < 2) // have to have at last 2 buttons to be a useful group
            return false;

        if (bBackward)
            std::reverse(aGroup.begin(), aGroup.end());

        auto aStart(std::find(aGroup.begin(), aGroup.end(), VclPtr<RadioButton>(pSourceWindow)));

        assert(aStart != aGroup.end());

        return focusNextInGroup(aStart, aGroup);
    }
}

namespace vcl {

bool Window::ImplDlgCtrl( const KeyEvent& rKEvt, bool bKeyInput )
{
    vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
    sal_uInt16  nKeyCode = aKeyCode.GetCode();
    vcl::Window* pSWindow;
    vcl::Window* pTempWindow;
    vcl::Window* pButtonWindow;
    sal_uInt16  i;
    sal_uInt16  iButton;
    sal_uInt16  iButtonStart;
    sal_uInt16  iTemp;
    sal_uInt16  nIndex;
    sal_uInt16  nFormStart;
    sal_uInt16  nFormEnd;
    DialogControlFlags nDlgCtrlFlags;

    // we cannot take over control without Focus-window
    vcl::Window* pFocusWindow = Application::GetFocusWindow();
    if ( !pFocusWindow || !ImplIsWindowOrChild( pFocusWindow ) )
        return false;

    // find Focus-Window in the child list
    pSWindow = ::ImplFindDlgCtrlWindow( this, pFocusWindow,
                                        nIndex, nFormStart, nFormEnd );
    if ( !pSWindow )
        return false;
    i = nIndex;

    nDlgCtrlFlags = DialogControlFlags::NONE;
    pTempWindow = pSWindow;
    do
    {
        nDlgCtrlFlags |= pTempWindow->GetDialogControlFlags();
        if ( pTempWindow == this )
            break;
        pTempWindow = pTempWindow->ImplGetParent();
    }
    while ( pTempWindow );

    pButtonWindow = nullptr;

    if ( nKeyCode == KEY_RETURN )
    {
        // search first for a DefPushButton/CancelButton
        pButtonWindow = ImplGetChildWindow( this, nFormStart, iButton, true );
        iButtonStart = iButton;
        while ( pButtonWindow )
        {
            if ( (pButtonWindow->GetStyle() & WB_DEFBUTTON) &&
                 pButtonWindow->mpWindowImpl->mbPushButton )
                break;

            pButtonWindow = ImplGetNextWindow( this, iButton, iButton, true );
            if ( (iButton <= iButtonStart) || (iButton > nFormEnd) )
                pButtonWindow = nullptr;
        }

        if ( bKeyInput && !pButtonWindow && (nDlgCtrlFlags & DialogControlFlags::Return) )
        {
            GetDlgWindowType nType;
            GetFocusFlags    nGetFocusFlags = GetFocusFlags::Tab;
            sal_uInt16  nNewIndex;
            sal_uInt16  iStart;
            if ( aKeyCode.IsShift() )
            {
                nType = GetDlgWindowType::Prev;
                nGetFocusFlags |= GetFocusFlags::Backward;
            }
            else
            {
                nType = GetDlgWindowType::Next;
                nGetFocusFlags |= GetFocusFlags::Forward;
            }
            iStart = i;
            pTempWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
            while ( pTempWindow && (pTempWindow != pSWindow) )
            {
                if ( !pTempWindow->mpWindowImpl->mbPushButton )
                {
                    // get Around-Flag
                    if ( nType == GetDlgWindowType::Prev )
                    {
                        if ( nNewIndex > iStart )
                            nGetFocusFlags |= GetFocusFlags::Around;
                    }
                    else
                    {
                        if ( nNewIndex < iStart )
                            nGetFocusFlags |= GetFocusFlags::Around;
                    }
                    pTempWindow->ImplControlFocus( nGetFocusFlags );
                    return true;
                }
                else
                {
                    i = nNewIndex;
                    pTempWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
                }
                if ( (i <= iStart) || (i > nFormEnd) )
                    pTempWindow = nullptr;
            }
            // if this is the same window, simulate a Get/LoseFocus,
            // in case AROUND is being processed
            if ( pTempWindow && (pTempWindow == pSWindow) )
            {
                NotifyEvent aNEvt1( NotifyEventType::LOSEFOCUS, pSWindow );
                if ( !ImplCallPreNotify( aNEvt1 ) )
                    pSWindow->CompatLoseFocus();
                pSWindow->mpWindowImpl->mnGetFocusFlags = nGetFocusFlags | GetFocusFlags::Around;
                NotifyEvent aNEvt2( NotifyEventType::GETFOCUS, pSWindow );
                if ( !ImplCallPreNotify( aNEvt2 ) )
                    pSWindow->CompatGetFocus();
                pSWindow->mpWindowImpl->mnGetFocusFlags = GetFocusFlags::NONE;
                return true;
            }
        }
    }
    else if ( nKeyCode == KEY_ESCAPE )
    {
        // search first for a DefPushButton/CancelButton
        pButtonWindow = ImplGetChildWindow( this, nFormStart, iButton, true );
        iButtonStart = iButton;
        while ( pButtonWindow )
        {
            if ( pButtonWindow->GetType() == WindowType::CANCELBUTTON )
                break;

            pButtonWindow = ImplGetNextWindow( this, iButton, iButton, true );
            if ( (iButton <= iButtonStart) || (iButton > nFormEnd) )
                pButtonWindow = nullptr;
        }

        if ( bKeyInput && mpWindowImpl->mpDlgCtrlDownWindow )
        {
            if ( mpWindowImpl->mpDlgCtrlDownWindow.get() != pButtonWindow )
            {
                mpWindowImpl->mpDlgCtrlDownWindow->SetPressed( false );
                mpWindowImpl->mpDlgCtrlDownWindow = nullptr;
                return true;
            }
        }
    }
    else if ( bKeyInput )
    {
        if ( nKeyCode == KEY_TAB )
        {
            // do not skip Alt key, for MS Windows
            if ( !aKeyCode.IsMod2() )
            {
                sal_uInt16  nNewIndex;
                bool        bForm = false;

                // for Ctrl-Tab check if we want to jump to next template
                if ( aKeyCode.IsMod1() )
                {
                    // search group
                    vcl::Window* pFormFirstWindow = nullptr;
                    vcl::Window* pLastFormFirstWindow = nullptr;
                    pTempWindow = ImplGetChildWindow( this, 0, iTemp, false );
                    vcl::Window* pPrevFirstFormFirstWindow = nullptr;
                    vcl::Window* pFirstFormFirstWindow = pTempWindow;
                    while ( pTempWindow )
                    {
                        if ( pTempWindow->ImplGetWindow()->IsDialogControlStart() )
                        {
                            if ( iTemp != 0 )
                                bForm = true;
                            if ( aKeyCode.IsShift() )
                            {
                                if ( iTemp <= nIndex )
                                    pFormFirstWindow = pPrevFirstFormFirstWindow;
                                pPrevFirstFormFirstWindow = pTempWindow;
                            }
                            else
                            {
                                if ( (iTemp > nIndex) && !pFormFirstWindow )
                                    pFormFirstWindow = pTempWindow;
                            }
                            pLastFormFirstWindow = pTempWindow;
                        }

                        pTempWindow = ImplGetNextWindow( this, iTemp, iTemp, false );
                        if ( !iTemp )
                            pTempWindow = nullptr;
                    }

                    if ( bForm )
                    {
                        if ( !pFormFirstWindow )
                        {
                            if ( aKeyCode.IsShift() )
                                pFormFirstWindow = pLastFormFirstWindow;
                            else
                                pFormFirstWindow = pFirstFormFirstWindow;
                        }

                        sal_uInt16 nFoundFormStart = 0;
                        sal_uInt16 nFoundFormEnd = 0;
                        sal_uInt16 nTempIndex = 0;
                        if ( ::ImplFindDlgCtrlWindow( this, pFormFirstWindow, nTempIndex,
                                                      nFoundFormStart, nFoundFormEnd ) )
                        {
                            nTempIndex = nFoundFormStart;
                            pFormFirstWindow = ImplGetDlgWindow( nTempIndex, GetDlgWindowType::First, nFoundFormStart, nFoundFormEnd );
                            if ( pFormFirstWindow )
                            {
                                pFormFirstWindow->ImplControlFocus();
                                return true;
                            }
                        }
                    }
                }

                if ( !bForm )
                {
                    // Only use Ctrl-TAB if it was allowed for the whole
                    // dialog or for the current control (#103667#)
                    if (!aKeyCode.IsMod1() || (pSWindow->GetStyle() & WB_NODIALOGCONTROL))
                    {
                        GetDlgWindowType nType;
                        GetFocusFlags    nGetFocusFlags = GetFocusFlags::Tab;
                        if ( aKeyCode.IsShift() )
                        {
                            nType = GetDlgWindowType::Prev;
                            nGetFocusFlags |= GetFocusFlags::Backward;
                        }
                        else
                        {
                            nType = GetDlgWindowType::Next;
                            nGetFocusFlags |= GetFocusFlags::Forward;
                        }
                        vcl::Window* pWindow = ImplGetDlgWindow( i, nType, nFormStart, nFormEnd, &nNewIndex );
                        // if this is the same window, simulate a Get/LoseFocus,
                        // in case AROUND is being processed
                        if ( pWindow == pSWindow )
                        {
                            NotifyEvent aNEvt1( NotifyEventType::LOSEFOCUS, pSWindow );
                            if ( !ImplCallPreNotify( aNEvt1 ) )
                                pSWindow->CompatLoseFocus();
                            pSWindow->mpWindowImpl->mnGetFocusFlags = nGetFocusFlags | GetFocusFlags::Around;
                            NotifyEvent aNEvt2( NotifyEventType::GETFOCUS, pSWindow );
                            if ( !ImplCallPreNotify( aNEvt2 ) )
                                pSWindow->CompatGetFocus();
                            pSWindow->mpWindowImpl->mnGetFocusFlags = GetFocusFlags::NONE;
                            return true;
                        }
                        else if ( pWindow )
                        {
                            // get Around-Flag
                            if ( nType == GetDlgWindowType::Prev )
                            {
                                if ( nNewIndex > i )
                                    nGetFocusFlags |= GetFocusFlags::Around;
                            }
                            else
                            {
                                if ( nNewIndex < i )
                                    nGetFocusFlags |= GetFocusFlags::Around;
                            }
                            pWindow->ImplControlFocus( nGetFocusFlags );
                            return true;
                        }
                    }
                }
            }
        }
        else if ( (nKeyCode == KEY_LEFT) || (nKeyCode == KEY_UP) )
        {
            if (pSWindow->GetType() == WindowType::RADIOBUTTON)
                return nextInGroup(static_cast<RadioButton*>(pSWindow), true);
            else
            {
                WinBits nStyle = pSWindow->GetStyle();
                if ( !(nStyle & WB_GROUP) )
                {
                    vcl::Window* pWindow = prevLogicalChildOfParent(this, pSWindow);
                    while ( pWindow )
                    {
                        pWindow = pWindow->ImplGetWindow();

                        nStyle = pWindow->GetStyle();

                        if (isSuitableDestination(pWindow))
                        {
                            if ( pWindow != pSWindow )
                                pWindow->ImplControlFocus( GetFocusFlags::CURSOR | GetFocusFlags::Backward );
                            return true;
                        }

                        if ( nStyle & WB_GROUP )
                            break;

                        pWindow = prevLogicalChildOfParent(this, pWindow);
                    }
                }
            }
        }
        else if ( (nKeyCode == KEY_RIGHT) || (nKeyCode == KEY_DOWN) )
        {
            if (pSWindow->GetType() == WindowType::RADIOBUTTON)
                return nextInGroup(static_cast<RadioButton*>(pSWindow), false);
            else
            {
                vcl::Window* pWindow = nextLogicalChildOfParent(this, pSWindow);
                while ( pWindow )
                {
                    pWindow = pWindow->ImplGetWindow();

                    WinBits nStyle = pWindow->GetStyle();

                    if ( nStyle & WB_GROUP )
                        break;

                    if (isSuitableDestination(pWindow))
                    {
                        pWindow->ImplControlFocus( GetFocusFlags::CURSOR | GetFocusFlags::Backward );
                        return true;
                    }

                    pWindow = nextLogicalChildOfParent(this, pWindow);
                }
            }
        }
        else
        {
            sal_Unicode c = rKEvt.GetCharCode();
            if ( c )
            {
                pSWindow = ::ImplFindAccelWindow( this, i, c, nFormStart, nFormEnd );
                if ( pSWindow )
                {
                    GetFocusFlags nGetFocusFlags = GetFocusFlags::Mnemonic;
                    if ( pSWindow == ::ImplFindAccelWindow( this, i, c, nFormStart, nFormEnd ) )
                        nGetFocusFlags |= GetFocusFlags::UniqueMnemonic;
#ifdef _WIN32
                    // tdf#157649 Allow omitting the Alt key when focus is in the dialog action area:
                    bool bIsButtonBox = dynamic_cast<VclButtonBox*>(pSWindow->GetParent()) != nullptr;
                    if ((bIsButtonBox && pSWindow->GetParent()->HasChildPathFocus(true)) || aKeyCode.IsMod2())
#else
                    if (aKeyCode.IsMod2())
#endif
                    {
                        pSWindow->ImplControlFocus( nGetFocusFlags );
                        return true;
                    }
                }
            }
        }
    }

    if (isSuitableDestination(pButtonWindow))
    {
        if ( bKeyInput )
        {
            if ( mpWindowImpl->mpDlgCtrlDownWindow && (mpWindowImpl->mpDlgCtrlDownWindow.get() != pButtonWindow) )
            {
                mpWindowImpl->mpDlgCtrlDownWindow->SetPressed( false );
                mpWindowImpl->mpDlgCtrlDownWindow = nullptr;
            }

            static_cast<PushButton*>(pButtonWindow)->SetPressed( true );
            mpWindowImpl->mpDlgCtrlDownWindow = static_cast<PushButton*>(pButtonWindow);
        }
        else if ( mpWindowImpl->mpDlgCtrlDownWindow.get() == pButtonWindow )
        {
            mpWindowImpl->mpDlgCtrlDownWindow = nullptr;
            static_cast<PushButton*>(pButtonWindow)->SetPressed( false );
            static_cast<PushButton*>(pButtonWindow)->Click();
        }

        return true;
    }

    return false;
}

// checks if this window has dialog control
bool Window::ImplHasDlgCtrl() const
{
    vcl::Window* pDlgCtrlParent;

    // lookup window for dialog control
    pDlgCtrlParent = ImplGetParent();
    while ( pDlgCtrlParent &&
            !pDlgCtrlParent->ImplIsOverlapWindow() &&
            ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
        pDlgCtrlParent = pDlgCtrlParent->ImplGetParent();

    return pDlgCtrlParent && ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL);
}

void Window::ImplDlgCtrlNextWindow()
{
    vcl::Window* pDlgCtrlParent;
    vcl::Window* pDlgCtrl;
    vcl::Window* pSWindow;
    sal_uInt16  nIndex;
    sal_uInt16  nFormStart;
    sal_uInt16  nFormEnd;

    // lookup window for dialog control
    pDlgCtrl = this;
    pDlgCtrlParent = ImplGetParent();
    while ( pDlgCtrlParent &&
            !pDlgCtrlParent->ImplIsOverlapWindow() &&
            ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
        pDlgCtrlParent = pDlgCtrlParent->ImplGetParent();

    if ( !pDlgCtrlParent || (GetStyle() & WB_NODIALOGCONTROL) || ((pDlgCtrlParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
        return;

    // lookup window in child list
    pSWindow = ::ImplFindDlgCtrlWindow( pDlgCtrlParent, pDlgCtrl,
                                        nIndex, nFormStart, nFormEnd );
    if ( !pSWindow )
        return;

    vcl::Window* pWindow = pDlgCtrlParent->ImplGetDlgWindow( nIndex, GetDlgWindowType::Next, nFormStart, nFormEnd );
    if ( pWindow && (pWindow != pSWindow) )
        pWindow->ImplControlFocus();
}

static void ImplDlgCtrlUpdateDefButton( vcl::Window* pParent, const vcl::Window* pFocusWindow,
                                        bool bGetFocus )
{
    PushButton* pOldDefButton   = nullptr;
    PushButton* pNewDefButton   = nullptr;
    vcl::Window*     pSWindow;
    sal_uInt16      i;
    sal_uInt16      nFormStart;
    sal_uInt16      nFormEnd;

    // find template
    pSWindow = ::ImplFindDlgCtrlWindow( pParent, pFocusWindow, i, nFormStart, nFormEnd );
    if ( !pSWindow )
    {
        nFormStart = 0;
        nFormEnd = 0xFFFF;
    }

    pSWindow = ImplGetChildWindow( pParent, nFormStart, i, false );
    while ( pSWindow )
    {
        if ( pSWindow->ImplIsPushButton() )
        {
            PushButton* pPushButton = static_cast<PushButton*>(pSWindow);
            if ( pPushButton->ImplIsDefButton() )
                pOldDefButton = pPushButton;
            if ( pPushButton->HasChildPathFocus() )
                pNewDefButton = pPushButton;
            else if ( !pNewDefButton && (pPushButton->GetStyle() & WB_DEFBUTTON) )
                pNewDefButton = pPushButton;
        }

        pSWindow = ImplGetNextWindow( pParent, i, i, false );
        if ( !i || (i > nFormEnd) )
            pSWindow = nullptr;
    }

    if ( !bGetFocus )
    {
        sal_uInt16 nDummy;
        vcl::Window* pNewFocusWindow = Application::GetFocusWindow();
        if ( !pNewFocusWindow || !pParent->ImplIsWindowOrChild( pNewFocusWindow ) )
            pNewDefButton = nullptr;
        else if ( !::ImplFindDlgCtrlWindow( pParent, pNewFocusWindow, i, nDummy, nDummy ) ||
                  (i < nFormStart) || (i > nFormEnd) )
            pNewDefButton = nullptr;
    }

    if ( pOldDefButton != pNewDefButton )
    {
        if ( pOldDefButton )
            pOldDefButton->ImplSetDefButton( false );
        if ( pNewDefButton )
            pNewDefButton->ImplSetDefButton( true );
    }
}

void Window::ImplDlgCtrlFocusChanged( const vcl::Window* pWindow, bool bGetFocus )
{
    if ( mpWindowImpl->mpDlgCtrlDownWindow && !bGetFocus )
    {
        mpWindowImpl->mpDlgCtrlDownWindow->SetPressed( false );
        mpWindowImpl->mpDlgCtrlDownWindow = nullptr;
    }

    ImplDlgCtrlUpdateDefButton( this, pWindow, bGetFocus );
}

vcl::Window* Window::ImplFindDlgCtrlWindow( const vcl::Window* pWindow )
{
    sal_uInt16  nIndex;
    sal_uInt16  nFormStart;
    sal_uInt16  nFormEnd;

    // find Focus-Window in the Child-List and return
    return ::ImplFindDlgCtrlWindow( this, pWindow, nIndex, nFormStart, nFormEnd );
}

KeyEvent Window::GetActivationKey() const
{
    KeyEvent aKeyEvent;

    sal_Unicode nAccel = getAccel( GetText() );
    if( ! nAccel )
    {
        vcl::Window* pWindow = GetAccessibleRelationLabeledBy();
        if( pWindow )
            nAccel = getAccel( pWindow->GetText() );
    }
    if( nAccel )
    {
        sal_uInt16 nCode = 0;
        if( nAccel >= 'a' && nAccel <= 'z' )
            nCode = KEY_A + (nAccel-'a');
        else if( nAccel >= 'A' && nAccel <= 'Z' )
            nCode = KEY_A + (nAccel-'A');
        else if( nAccel >= '0' && nAccel <= '9' )
            nCode = KEY_0 + (nAccel-'0');
        else if( nAccel == '.' )
            nCode = KEY_POINT;
        else if( nAccel == '-' )
            nCode = KEY_SUBTRACT;
        vcl::KeyCode aKeyCode( nCode, falsefalsetruefalse );
        aKeyEvent = KeyEvent( nAccel, aKeyCode );
    }
    return aKeyEvent;
}

/* namespace vcl */

sal_Unicode getAccel( std::u16string_view rStr )
{
    sal_Unicode nChar = 0;
    size_t nPos = 0;
    do
    {
        nPos = rStr.find( '~', nPos );
        if( nPos != std::u16string_view::npos && nPos < rStr.size() )
            nChar = rStr[ ++nPos ];
        else
            nChar = 0;
    } while( nChar == '~' );
    return nChar;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=89 G=91

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.