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 <boost/optional.hpp>
29 
30 namespace vcl
31 {
32 
34  {
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  bEnabled( true )
102  {
103  }
104 
106  {
107  }
108 
110  {
111  bEnabled = b;
112  }
113 
115  {
116  if( bEnabled )
117  {
118  sal_Unicode c = _keyEvent.GetCharCode();
119 
120  if ( ( c >= 32 ) && ( c != 127 ) && !_keyEvent.GetKeyCode().IsMod2() )
121  {
122  m_pData->sCurrentSearchString += OUStringLiteral1(c);
123  SAL_INFO( "vcl", "QuickSelectionEngine::HandleKeyEvent: searching for " << m_pData->sCurrentSearchString );
124 
125  if ( m_pData->sCurrentSearchString.getLength() == 1 )
126  { // first character in the search -> remember
127  m_pData->aSingleSearchChar = c;
128  }
129  else if ( m_pData->sCurrentSearchString.getLength() > 1 )
130  {
131  if ( !!m_pData->aSingleSearchChar && ( *m_pData->aSingleSearchChar != c ) )
132  // we already have a "single char", but the current one is different -> reset
133  m_pData->aSingleSearchChar.reset();
134  }
135 
136  OUString aSearchTemp( m_pData->sCurrentSearchString );
137 
138  StringEntryIdentifier pMatchingEntry = findMatchingEntry( aSearchTemp, *m_pData );
139  SAL_INFO( "vcl", "QuickSelectionEngine::HandleKeyEvent: found " << pMatchingEntry );
140  if ( !pMatchingEntry && (aSearchTemp.getLength() > 1) && !!m_pData->aSingleSearchChar )
141  {
142  // if there's only one letter in the search string, use a different search mode
143  aSearchTemp = OUString(*m_pData->aSingleSearchChar);
144  pMatchingEntry = findMatchingEntry( aSearchTemp, *m_pData );
145  }
146 
147  if ( pMatchingEntry )
148  {
149  m_pData->rEntryList.SelectEntry( pMatchingEntry );
150  m_pData->aSearchTimeout.Start();
151  }
152  else
153  {
154  lcl_reset( *m_pData );
155  }
156 
157  return true;
158  }
159  return false;
160  }
161  else
162  {
163  return false;
164  }
165  }
166 
168  {
169  if( bEnabled )
170  lcl_reset( *m_pData );
171  }
172 
173 } // namespace vcl
174 
175 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool HandleKeyEvent(const KeyEvent &_rKEvt)
::boost::optional< sal_Unicode > aSingleSearchChar
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:705
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
const void * StringEntryIdentifier
DECL_LINK(SearchStringTimeout, Timer *, void)
ISearchableStringList & rEntryList
QuickSelectionEngine(ISearchableStringList &_entryList)
void SetTimeout(sal_uInt64 nTimeoutMs)
Definition: timer.cxx:89
const vcl::I18nHelper & GetLocaleI18nHelper() const
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:53
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:594
#define SAL_INFO(area, stream)
sal_Unicode GetCharCode() const
Definition: event.hxx:52
void SetInvokeHandler(const Link< Timer *, void > &rLink)
Definition: timer.hxx:57
Definition: timer.hxx:26
QuickSelectionEngine_Data(ISearchableStringList &_entryList)
IMPL_LINK_NOARG(QuickSelectionEngine_Data, SearchStringTimeout, Timer *, void)
void SetDebugName(const sal_Char *pDebugName)
Definition: task.hxx:82
bool IsMod2() const
Definition: keycod.hxx:62