diff options
Diffstat (limited to 'vcl/source/window/accmgr.cxx')
-rw-r--r-- | vcl/source/window/accmgr.cxx | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/vcl/source/window/accmgr.cxx b/vcl/source/window/accmgr.cxx new file mode 100644 index 000000000..26ea9846e --- /dev/null +++ b/vcl/source/window/accmgr.cxx @@ -0,0 +1,228 @@ +/* -*- 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 <accel.hxx> +#include <accmgr.hxx> + +#include <algorithm> + +ImplAccelManager::~ImplAccelManager() +{ +} + +bool ImplAccelManager::InsertAccel( Accelerator* pAccel ) +{ + if ( !mxAccelList ) { + mxAccelList.emplace(); + } else { + for (Accelerator* i : *mxAccelList) { + if ( i == pAccel ) { + return false; + } + } + } + + mxAccelList->insert( mxAccelList->begin(), pAccel ); + return true; +} + +void ImplAccelManager::RemoveAccel( Accelerator const * pAccel ) +{ + // do we have a list ? + if ( !mxAccelList ) + return; + + //e.g. #i90599#. Someone starts typing a sequence in a dialog, but doesn't + //end it, and then closes the dialog, deleting the accelerators. So if + //we're removing an accelerator that a sub-accelerator which is in the + //sequence list, throw away the entire sequence + if ( mxSequenceList ) { + for (sal_uInt16 i = 0; i < pAccel->GetItemCount(); ++i) { + Accelerator* pSubAccel = pAccel->GetAccel( pAccel->GetItemId(i) ); + for (Accelerator* j : *mxSequenceList) { + if ( j == pSubAccel ) { + EndSequence(); + i = pAccel->GetItemCount(); + break; + } + } + } + } + + // throw it away + auto it = std::find(mxAccelList->begin(), mxAccelList->end(), pAccel); + if (it != mxAccelList->end()) + mxAccelList->erase( it ); +} + +void ImplAccelManager::EndSequence() +{ + // are we in a list ? + if ( !mxSequenceList ) + return; + + for (Accelerator* pTempAccel : *mxSequenceList) + { + pTempAccel->mpDel = nullptr; + } + + // delete sequence-list + mxSequenceList.reset(); +} + +bool ImplAccelManager::IsAccelKey( const vcl::KeyCode& rKeyCode ) +{ + Accelerator* pAccel; + + // do we have accelerators ?? + if ( !mxAccelList ) + return false; + if ( mxAccelList->empty() ) + return false; + + // are we in a sequence ? + if ( mxSequenceList ) + { + pAccel = mxSequenceList->empty() ? nullptr : (*mxSequenceList)[ 0 ]; + + // not found ? + if ( !pAccel ) + { + // abort sequence + FlushAccel(); + return false; + } + + // can the entry be found ? + ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode ); + if ( pEntry ) + { + Accelerator* pNextAccel = pEntry->mpAccel; + + // is an accelerator coupled ? + if ( pNextAccel ) + { + + mxSequenceList->insert( mxSequenceList->begin(), pNextAccel ); + + // call Activate-Handler of the new one + pNextAccel->Activate(); + return true; + } + else + { + // it is there already ! + if ( pEntry->mbEnabled ) + { + // stop sequence (first call deactivate-handler) + EndSequence(); + + // set accelerator of the actual item + // and call the handler + bool bDel = false; + pAccel->mnCurId = pEntry->mnId; + pAccel->mpDel = &bDel; + pAccel->Select(); + + // did the accelerator survive the call + if ( !bDel ) + { + pAccel->mnCurId = 0; + pAccel->mpDel = nullptr; + } + + return true; + } + else + { + // stop sequence as the accelerator was disabled + // transfer the key (to the system) + FlushAccel(); + return false; + } + } + } + else + { + // wrong key => stop sequence + FlushAccel(); + return false; + } + } + + // step through the list of accelerators + for (Accelerator* i : *mxAccelList) + { + pAccel = i; + + // is the entry contained ? + ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode ); + if ( pEntry ) + { + Accelerator* pNextAccel = pEntry->mpAccel; + + // is an accelerator assigned ? + if ( pNextAccel ) + { + + // create sequence list + mxSequenceList.emplace(); + mxSequenceList->insert( mxSequenceList->begin(), pAccel ); + mxSequenceList->insert( mxSequenceList->begin(), pNextAccel ); + + // call activate-Handler of the new one + pNextAccel->Activate(); + + return true; + } + else + { + // already assigned ! + if ( pEntry->mbEnabled ) + { + // first call activate/deactivate-Handler + pAccel->Activate(); + + // define accelerator of the actual item + // and call the handler + bool bDel = false; + pAccel->mnCurId = pEntry->mnId; + pAccel->mpDel = &bDel; + pAccel->Select(); + + // if the accelerator did survive the call + if ( !bDel ) + { + pAccel->mnCurId = 0; + pAccel->mpDel = nullptr; + } + + return true; + } + else + return false; + } + } + } + + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |