LibreOffice Module vcl (master)  1
quickselectionengine.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
21 #include <vcl/event.hxx>
22 #include <vcl/timer.hxx>
23 #include <vcl/i18nhelp.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/settings.hxx>
26 #include <sal/log.hxx>
27 
28 #include <optional>
29 
30 namespace vcl
31 {
32 
34  {
37  ::std::optional< sal_Unicode > aSingleSearchChar;
39 
41  :rEntryList( _entryList )
42  ,sCurrentSearchString()
43  ,aSingleSearchChar()
44  ,aSearchTimeout()
45  {
46  aSearchTimeout.SetTimeout( 2500 );
47  aSearchTimeout.SetInvokeHandler( LINK( this, QuickSelectionEngine_Data, SearchStringTimeout ) );
48  aSearchTimeout.SetDebugName( "vcl::QuickSelectionEngine_Data aSearchTimeout" );
49  }
50 
52  {
53  aSearchTimeout.Stop();
54  }
55 
56  DECL_LINK( SearchStringTimeout, Timer*, void );
57  };
58 
59  namespace
60  {
61  void lcl_reset( QuickSelectionEngine_Data& _data )
62  {
63  _data.sCurrentSearchString.clear();
64  _data.aSingleSearchChar.reset();
65  _data.aSearchTimeout.Stop();
66  }
67  }
68 
69  IMPL_LINK_NOARG( QuickSelectionEngine_Data, SearchStringTimeout, Timer*, void )
70  {
71  lcl_reset( *this );
72  }
73 
74  static StringEntryIdentifier findMatchingEntry( const OUString& _searchString, QuickSelectionEngine_Data const & _engineData )
75  {
77  // TODO: do we really need the Window's settings here? The original code used it ...
78 
79  OUString sEntryText;
80  // get the "current + 1" entry
81  StringEntryIdentifier pSearchEntry = _engineData.rEntryList.CurrentEntry( sEntryText );
82  if ( pSearchEntry )
83  pSearchEntry = _engineData.rEntryList.NextEntry( pSearchEntry, sEntryText );
84  // loop 'til we find another matching entry
85  StringEntryIdentifier pStartedWith = pSearchEntry;
86  while ( pSearchEntry )
87  {
88  if ( rI18nHelper.MatchString( _searchString, sEntryText ) )
89  break;
90 
91  pSearchEntry = _engineData.rEntryList.NextEntry( pSearchEntry, sEntryText );
92  if ( pSearchEntry == pStartedWith )
93  pSearchEntry = nullptr;
94  }
95 
96  return pSearchEntry;
97  }
98 
100  :m_pData( new QuickSelectionEngine_Data( _entryList ) )
101  {
102  }
103 
105  {
106  }
107 
109  {
110  sal_Unicode c = _keyEvent.GetCharCode();
111 
112  if ( ( c >= 32 ) && ( c != 127 ) && !_keyEvent.GetKeyCode().IsMod2() )
113  {
114  m_pData->sCurrentSearchString += OUStringChar(c);
115  SAL_INFO( "vcl", "QuickSelectionEngine::HandleKeyEvent: searching for " << m_pData->sCurrentSearchString );
116 
117  if ( m_pData->sCurrentSearchString.getLength() == 1 )
118  { // first character in the search -> remember
119  m_pData->aSingleSearchChar = c;
120  }
121  else if ( m_pData->sCurrentSearchString.getLength() > 1 )
122  {
123  if ( !!m_pData->aSingleSearchChar && ( *m_pData->aSingleSearchChar != c ) )
124  // we already have a "single char", but the current one is different -> reset
125  m_pData->aSingleSearchChar.reset();
126  }
127 
128  OUString aSearchTemp( m_pData->sCurrentSearchString );
129 
130  StringEntryIdentifier pMatchingEntry = findMatchingEntry( aSearchTemp, *m_pData );
131  SAL_INFO( "vcl", "QuickSelectionEngine::HandleKeyEvent: found " << pMatchingEntry );
132  if ( !pMatchingEntry && (aSearchTemp.getLength() > 1) && !!m_pData->aSingleSearchChar )
133  {
134  // if there's only one letter in the search string, use a different search mode
135  aSearchTemp = OUString(*m_pData->aSingleSearchChar);
136  pMatchingEntry = findMatchingEntry( aSearchTemp, *m_pData );
137  }
138 
139  if ( pMatchingEntry )
140  {
141  m_pData->rEntryList.SelectEntry( pMatchingEntry );
142  m_pData->aSearchTimeout.Start();
143  }
144  else
145  {
146  lcl_reset( *m_pData );
147  }
148 
149  return true;
150  }
151  return false;
152  }
153 
155  {
156  lcl_reset( *m_pData );
157  }
158 
159 } // namespace vcl
160 
161 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool HandleKeyEvent(const KeyEvent &_rKEvt)
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:715
virtual StringEntryIdentifier CurrentEntry(OUString &_out_entryText) const =0
returns the current entry in the list of searchable strings.
bool MatchString(const OUString &rStr1, const OUString &rStr2) const
Definition: i18nhelp.cxx:124
::std::unique_ptr< QuickSelectionEngine_Data > m_pData
sal_uInt16 sal_Unicode
FmFilterData * m_pData
const void * StringEntryIdentifier
DECL_LINK(SearchStringTimeout, Timer *, void)
ISearchableStringList & rEntryList
void SetDebugName(const char *pDebugName)
Definition: task.hxx:81
QuickSelectionEngine(ISearchableStringList &_entryList)
::std::optional< sal_Unicode > aSingleSearchChar
void SetTimeout(sal_uInt64 nTimeoutMs)
Definition: timer.cxx:89
const vcl::I18nHelper & GetLocaleI18nHelper() const
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:54
virtual StringEntryIdentifier NextEntry(StringEntryIdentifier _currentEntry, OUString &_out_entryText) const =0
returns the next entry in the list.
static StringEntryIdentifier findMatchingEntry(const OUString &_searchString, QuickSelectionEngine_Data const &_engineData)
void Stop()
Definition: scheduler.cxx:593
#define SAL_INFO(area, stream)
sal_Unicode GetCharCode() const
Definition: event.hxx:53
void SetInvokeHandler(const Link< Timer *, void > &rLink)
Definition: timer.hxx:56
Definition: timer.hxx:26
QuickSelectionEngine_Data(ISearchableStringList &_entryList)
IMPL_LINK_NOARG(QuickSelectionEngine_Data, SearchStringTimeout, Timer *, void)
bool IsMod2() const
Definition: keycod.hxx:62