NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
searchctrl.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2019 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "searchctrl.hpp"
20#include <wx/dnd.h>
21
22#define HIGHLIGHTCOLOR wxColour(0,0,139)
23
24
28 EVT_KEY_DOWN(SearchCtrlPopup::OnKeyEvent)
29 EVT_LIST_BEGIN_DRAG(-1, SearchCtrlPopup::OnDragStart)
30wxEND_EVENT_TABLE()
31
32
42wxArrayString SearchCtrlPopup::split(wxString sString)
43{
44 wxArrayString ret;
45
46 // Append a '~' char, which makes the
47 // splitting more easy
48 sString += '~';
49
50 // Split the string in single strings
51 do
52 {
53 ret.Add(sString.substr(0, sString.find('~')));
54 sString.erase(0, sString.find('~')+1);
55 }
56 while (sString.length());
57
58 return ret;
59}
60
61
71{
72 if (m_ListId >= 0 && m_ListId < GetItemCount())
73 return wxListView::GetItemText(m_ListId);
74
75 return wxEmptyString;
76}
77
78
89void SearchCtrlPopup::OnKeyEvent(wxKeyEvent& event)
90{
91 wxChar chr = event.GetUnicodeKey();
92
93 //wxLogDebug("Key: %d", chr);
94
95 // Uppercase
96 if (chr != WXK_NONE)
97 {
98 if (event.ControlDown() && event.AltDown())
99 {
100 switch (chr)
101 {
102 case 'Q':
103 m_combo->WriteText('@');
104 break;
105 case '+':
106 m_combo->WriteText('~');
107 break;
108 case '7':
109 m_combo->WriteText('{');
110 break;
111 case '8':
112 m_combo->WriteText('[');
113 break;
114 case '9':
115 m_combo->WriteText(']');
116 break;
117 case '0':
118 m_combo->WriteText('}');
119 break;
120 case 223:
121 m_combo->WriteText('\\');
122 break;
123 case '<':
124 m_combo->WriteText('|');
125 break;
126 }
127 }
128 else if (chr >='A' && chr < WXK_DELETE)
129 {
130 if (event.ShiftDown())
131 m_combo->WriteText(chr);
132 else
133 m_combo->WriteText(wxChar(chr + 'a'-'A'));
134 }
135 else if (chr < 32 || chr == WXK_DELETE)
136 {
137 switch (chr)
138 {
139 case WXK_BACK:
140 m_combo->Remove(m_combo->GetInsertionPoint()-1, m_combo->GetInsertionPoint());
141 break;
142 case WXK_DELETE:
143 m_combo->Remove(m_combo->GetInsertionPoint(), m_combo->GetInsertionPoint()+1);
144 break;
145 case WXK_ESCAPE:
146 Dismiss();
147 break;
148 case WXK_RETURN:
149 if (GetItemCount() && !GetFirstSelected())
150 m_ListId = 0;
151 else if (GetFirstSelected())
152 m_ListId = GetFirstSelected();
153
154 Dismiss();
155 break;
156 }
157 }
158 else
159 {
160 if (!event.ShiftDown())
161 {
162 switch (chr)
163 {
164 case 246: // ö
165 m_combo->WriteText('ö');
166 break;
167 case 228: // ä
168 m_combo->WriteText('ä');
169 break;
170 case 252: // ü
171 m_combo->WriteText('ü');
172 break;
173 case 223: // ß
174 m_combo->WriteText('ß');
175 break;
176 default:
177 m_combo->WriteText(chr);
178 }
179 }
180 else
181 {
182 switch (chr)
183 {
184 case '-':
185 m_combo->WriteText('_');
186 break;
187 case '.':
188 m_combo->WriteText(':');
189 break;
190 case ',':
191 m_combo->WriteText(';');
192 break;
193 case '<':
194 m_combo->WriteText('>');
195 break;
196 case '#':
197 m_combo->WriteText('\'');
198 break;
199 case '+':
200 m_combo->WriteText('*');
201 break;
202 case '1':
203 m_combo->WriteText('!');
204 break;
205 case '2':
206 m_combo->WriteText('"');
207 break;
208 case '3':
209 m_combo->WriteText('§');
210 break;
211 case '4':
212 m_combo->WriteText('$');
213 break;
214 case '5':
215 m_combo->WriteText('%');
216 break;
217 case '6':
218 m_combo->WriteText('&');
219 break;
220 case '7':
221 m_combo->WriteText('/');
222 break;
223 case '8':
224 m_combo->WriteText('(');
225 break;
226 case '9':
227 m_combo->WriteText(')');
228 break;
229 case '0':
230 m_combo->WriteText('=');
231 break;
232 case 246: // ö
233 m_combo->WriteText('Ö');
234 break;
235 case 228: // ä
236 m_combo->WriteText('Ä');
237 break;
238 case 252: // ü
239 m_combo->WriteText('Ü');
240 break;
241 case 223: // ß
242 m_combo->WriteText('?');
243 break;
244 }
245 }
246 }
247 }
248 else
249 {
250 switch (event.GetKeyCode())
251 {
252 case WXK_UP:
253 if (!GetSelectedItemCount() || !GetFirstSelected())
254 Select(GetItemCount()-1);
255 else
256 Select(GetFirstSelected()-1);
257
258 EnsureVisible(GetFirstSelected());
259 break;
260 case WXK_LEFT:
261 m_combo->SetInsertionPoint(m_combo->GetInsertionPoint()-1);
262 break;
263 case WXK_DOWN:
264 if (!GetSelectedItemCount() || GetFirstSelected() == GetItemCount()-1)
265 Select(0);
266 else
267 Select(GetFirstSelected()+1);
268
269 EnsureVisible(GetFirstSelected());
270 break;
271 case WXK_RIGHT:
272 m_combo->SetInsertionPoint(m_combo->GetInsertionPoint()+1);
273 break;
274 case WXK_HOME:
275 m_combo->SetInsertionPoint(0);
276 break;
277 case WXK_END:
278 m_combo->SetInsertionPointEnd();
279 break;
280 }
281 }
282
283 event.Skip();
284}
285
286
295void SearchCtrlPopup::OnMouseUp(wxMouseEvent& WXUNUSED(event))
296{
297 m_ListId = wxListView::GetFirstSelected();
298 Dismiss();
299}
300
301
310void SearchCtrlPopup::OnMouseMove(wxMouseEvent& event)
311{
312 int flags = 0;
313 int id = HitTest(event.GetPosition(), flags, nullptr);
314
315 if (id != wxNOT_FOUND && (flags & wxLIST_HITTEST_ONITEM) && wxListView::GetFirstSelected() != id)
316 {
317 wxListView::Select(id);
318
319 if (m_enableColors && m_callTipHighlight.length() && GetItemTextColour(id) == HIGHLIGHTCOLOR)
320 SetToolTip(m_callTipHighlight);
321 else if (m_callTip.length())
322 SetToolTip(m_callTip);
323 }
324}
325
326
335void SearchCtrlPopup::OnDragStart(wxListEvent& event)
336{
337 wxString token = static_cast<SearchCtrl*>(m_combo)->getDragDropText(event.GetText());
338
339 if (!m_enableDragDrop)
340 {
341 event.Veto();
342 return;
343 }
344
345 wxTextDataObject _dataObject(token);
346 wxDropSource dragSource(this);
347 dragSource.SetData(_dataObject);
348 dragSource.DoDragDrop(wxDrag_AllowMove);
349
350 m_ListId = -1;
351 Dismiss();
352}
353
354
363void SearchCtrlPopup::Set(wxArrayString& stringArray)
364{
365 // Clear everything
366 ClearAll();
367
368 // Create the columns
369 for (size_t i = 0; i < m_sizes.size(); i++)
370 AppendColumn(wxEmptyString, wxLIST_FORMAT_LEFT, m_sizes[i]);
371
372 // Fill the lines with the passed strings,
373 // either in single- or multi-column fashion
374 for (size_t i = 0; i < stringArray.size(); i++)
375 {
376 if (m_sizes.size() == 1)
377 InsertItem(i, stringArray[i]);
378 else
379 {
380 wxArrayString strings = split(stringArray[i]);
381 InsertItem(i, strings[0]);
382
383 for (size_t j = 1; j < std::min(m_sizes.size(), strings.size()); j++)
384 SetItem(i, j, strings[j]);
385
386 if (m_enableColors && strings[0].find('(') != std::string::npos)
387 SetItemTextColour(i, HIGHLIGHTCOLOR);
388 }
389 }
390}
391
392
396
397
398BEGIN_EVENT_TABLE(SearchCtrl, wxComboCtrl)
399 EVT_COMBOBOX_CLOSEUP(-1, SearchCtrl::OnItemSelect)
400 EVT_TEXT(-1, SearchCtrl::OnTextChange)
401 EVT_ENTER_WINDOW(SearchCtrl::OnMouseEnter)
403
404
405
414bool SearchCtrl::selectItem(const wxString& value)
415{
416 // Do nothing in this implementation, because we have no
417 // container assigned
418 return true;
419}
420
421
431wxString SearchCtrl::getDragDropText(const wxString& value)
432{
433 return value;
434}
435
436
447wxArrayString SearchCtrl::getCandidates(const wxString& enteredText)
448{
449 // Will only return a copy of the entered text
450 wxArrayString stringArray(1, &enteredText);
451
452 return stringArray;
453}
454
455
465void SearchCtrl::OnItemSelect(wxCommandEvent& event)
466{
467 wxString value = GetValue();
468
469 if (value.length())
470 {
471 if (selectItem(value))
472 Clear();
473 }
474}
475
476
488void SearchCtrl::OnTextChange(wxCommandEvent& event)
489{
490 textEntryValue = GetValue();
491
492 if (textEntryValue.length() > 2 && !textChangeMutex)
493 {
494 textChangeMutex = true;
495
496 // Get the candidates matching to the entered text
497 wxArrayString candidates = getCandidates(textEntryValue);
498
499 // If the candidates exist, enter them in the
500 // list part and show it
501 if (candidates.size())
502 {
503 int insertionPoint = GetInsertionPoint();
504 popUp->Set(candidates);
505 SetValue(textEntryValue);
506
507 if (IsPopupWindowState(wxComboCtrl::Hidden))
508 Popup();
509
510 SelectNone();
511 SetInsertionPoint(insertionPoint);
512 }
513
514 textChangeMutex = false;
515 }
516}
517
518
530void SearchCtrl::OnMouseEnter(wxMouseEvent& event)
531{
532 if (GetValue().length() > 2 && IsPopupWindowState(wxComboCtrl::Hidden))
533 Popup();
534
535 SelectNone();
536 SetInsertionPointEnd();
537}
538
Implementation of a generic search control based on a combo box.
Definition: searchctrl.hpp:135
virtual wxArrayString getCandidates(const wxString &enteredText)
Child classes must override this member function to provide the candidates to be filled into the popu...
Definition: searchctrl.cpp:447
void OnMouseEnter(wxMouseEvent &event)
This event handler will show the drop down list, if the text field contains data and the mouse enters...
Definition: searchctrl.cpp:530
wxString textEntryValue
Definition: searchctrl.hpp:138
bool textChangeMutex
Definition: searchctrl.hpp:137
void OnItemSelect(wxCommandEvent &event)
This event handler function will be fired, if the user selects a proposed string in the opened dropdo...
Definition: searchctrl.cpp:465
SearchCtrlPopup * popUp
Definition: searchctrl.hpp:143
virtual wxString getDragDropText(const wxString &value)
Child classes may override this member function to provide a custom string for the built-in drag-drop...
Definition: searchctrl.cpp:431
void OnTextChange(wxCommandEvent &event)
This event handler function will be fired, if the user changes the text in the control....
Definition: searchctrl.cpp:488
virtual bool selectItem(const wxString &value)
Child classes may override this member function to do something, when the user selects an item in the...
Definition: searchctrl.cpp:414
The popup control for the generic search control. Implemented ontop of a list view.
Definition: searchctrl.hpp:32
wxArrayString split(wxString sString)
wxArrayInt m_sizes
Definition: searchctrl.hpp:37
void OnMouseUp(wxMouseEvent &WXUNUSED(event))
This event handler fires, if the user double clicks on an item in the popup list.
Definition: searchctrl.cpp:295
wxString m_callTipHighlight
Definition: searchctrl.hpp:39
virtual wxString GetStringValue() const override
Returns the string representation of the selected item after the popup had been closed.
Definition: searchctrl.cpp:70
void Set(wxArrayString &stringArray)
A set function to update the contents in the displayed list.
Definition: searchctrl.cpp:363
void OnMouseMove(wxMouseEvent &event)
This event handler provides the mouse hover effect in the popup list.
Definition: searchctrl.cpp:310
void OnDragStart(wxListEvent &event)
This event handler is the drag-drop handler for the search results.
Definition: searchctrl.cpp:335
wxString m_callTip
Definition: searchctrl.hpp:38
void OnKeyEvent(wxKeyEvent &event)
This event handler is necessary to pass the keycodes, which are accidentally catched in this control,...
Definition: searchctrl.cpp:89
#define min(a, b)
Definition: resampler.cpp:34
#define HIGHLIGHTCOLOR
Definition: searchctrl.cpp:22
wxBEGIN_EVENT_TABLE(SearchCtrlPopup, wxListView) wxEND_EVENT_TABLE() wxArrayString SearchCtrlPopup
This private member function splits the passed string at every '~' character in single strings,...
Definition: searchctrl.cpp:25
std::vector< std::string > split(const std::string &sStr, char cSplit)
Splits a vector at the selected characters.
END_EVENT_TABLE()