Character search moved to separate thread for smoother experience
This commit is contained in:
parent
710937f8df
commit
155fb03c5a
@ -2432,7 +2432,7 @@
|
|||||||
<property name="search_button">1</property>
|
<property name="search_button">1</property>
|
||||||
<property name="show">1</property>
|
<property name="show">1</property>
|
||||||
<property name="size"></property>
|
<property name="size"></property>
|
||||||
<property name="style">wxTE_PROCESS_ENTER</property>
|
<property name="style"></property>
|
||||||
<property name="subclass"></property>
|
<property name="subclass"></property>
|
||||||
<property name="toolbar_pane">0</property>
|
<property name="toolbar_pane">0</property>
|
||||||
<property name="tooltip"></property>
|
<property name="tooltip"></property>
|
||||||
@ -2469,7 +2469,7 @@
|
|||||||
<event name="OnSetFocus"></event>
|
<event name="OnSetFocus"></event>
|
||||||
<event name="OnSize"></event>
|
<event name="OnSize"></event>
|
||||||
<event name="OnText">OnSearchText</event>
|
<event name="OnText">OnSearchText</event>
|
||||||
<event name="OnTextEnter">OnSearchEnter</event>
|
<event name="OnTextEnter"></event>
|
||||||
<event name="OnUpdateUI"></event>
|
<event name="OnUpdateUI"></event>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
@ -3506,15 +3506,6 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="wxTimer" expanded="0">
|
|
||||||
<property name="enabled">0</property>
|
|
||||||
<property name="id">wxID_TIMER_SEARCH</property>
|
|
||||||
<property name="name">m_timerSearch</property>
|
|
||||||
<property name="oneshot">1</property>
|
|
||||||
<property name="period">1000</property>
|
|
||||||
<property name="permission">protected</property>
|
|
||||||
<event name="OnTimer">OnSearchTimer</event>
|
|
||||||
</object>
|
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</wxFormBuilder_Project>
|
</wxFormBuilder_Project>
|
||||||
|
@ -20,32 +20,22 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
|
||||||
static int __cdecl compare_hits(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
const std::pair<unsigned long, wchar_t> *_a = (const std::pair<unsigned long, wchar_t>*)a;
|
|
||||||
const std::pair<unsigned long, wchar_t> *_b = (const std::pair<unsigned long, wchar_t>*)b;
|
|
||||||
|
|
||||||
if (_a->first > _b->first) return -1;
|
|
||||||
else if (_a->first < _b->first) return 1;
|
|
||||||
|
|
||||||
if (_a->second < _b->second) return -1;
|
|
||||||
else if (_a->second > _b->second) return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// wxZRColaCharSelect
|
// wxZRColaCharSelect
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
wxDEFINE_EVENT(wxEVT_SEARCH_COMPLETE, wxThreadEvent);
|
||||||
|
|
||||||
|
|
||||||
wxZRColaCharSelect::wxZRColaCharSelect(wxWindow* parent) :
|
wxZRColaCharSelect::wxZRColaCharSelect(wxWindow* parent) :
|
||||||
m_searchChanged(false),
|
m_searchChanged(false),
|
||||||
m_unicodeChanged(false),
|
m_unicodeChanged(false),
|
||||||
m_char(0),
|
m_char(0),
|
||||||
|
m_searchThread(NULL),
|
||||||
wxZRColaCharSelectBase(parent)
|
wxZRColaCharSelectBase(parent)
|
||||||
{
|
{
|
||||||
|
Connect(wxID_ANY, wxEVT_SEARCH_COMPLETE, wxThreadEventHandler(wxZRColaCharSelect::OnSearchComplete), NULL, this);
|
||||||
|
|
||||||
m_unicode->SetValidator(wxHexValidator<wchar_t>(&m_char));
|
m_unicode->SetValidator(wxHexValidator<wchar_t>(&m_char));
|
||||||
|
|
||||||
// Fill categories.
|
// Fill categories.
|
||||||
@ -61,6 +51,15 @@ wxZRColaCharSelect::wxZRColaCharSelect(wxWindow* parent) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxZRColaCharSelect::~wxZRColaCharSelect()
|
||||||
|
{
|
||||||
|
if (m_searchThread)
|
||||||
|
m_searchThread->Delete();
|
||||||
|
|
||||||
|
Disconnect(wxID_ANY, wxEVT_SEARCH_COMPLETE, wxThreadEventHandler(wxZRColaCharSelect::OnSearchComplete), NULL, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void wxZRColaCharSelect::OnIdle(wxIdleEvent& event)
|
void wxZRColaCharSelect::OnIdle(wxIdleEvent& event)
|
||||||
{
|
{
|
||||||
event.Skip();
|
event.Skip();
|
||||||
@ -90,7 +89,31 @@ void wxZRColaCharSelect::OnIdle(wxIdleEvent& event)
|
|||||||
|
|
||||||
m_unicodeChanged = false;
|
m_unicodeChanged = false;
|
||||||
} else if (m_searchChanged) {
|
} else if (m_searchChanged) {
|
||||||
m_timerSearch.Start(1000, true);
|
if (m_searchThread)
|
||||||
|
m_searchThread->Delete();
|
||||||
|
|
||||||
|
wxString val(m_search->GetValue());
|
||||||
|
if (!val.IsEmpty()) {
|
||||||
|
ZRColaApp *app = (ZRColaApp*)wxTheApp;
|
||||||
|
|
||||||
|
m_searchThread = new SearchThread(this);
|
||||||
|
|
||||||
|
m_searchThread->m_search.assign(val.c_str(), val.Length());
|
||||||
|
|
||||||
|
// Select categories.
|
||||||
|
for (size_t i = 0, n = app->m_cc_db.idxRnk.size(); i < n; i++) {
|
||||||
|
const ZRCola::chrcat_db::chrcat &cc = app->m_cc_db.idxRnk[i];
|
||||||
|
if (m_categories->IsChecked(i))
|
||||||
|
m_searchThread->m_cats.insert(cc.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_searchThread->Run() != wxTHREAD_NO_ERROR) {
|
||||||
|
wxFAIL_MSG("Can't create the thread!");
|
||||||
|
delete m_searchThread;
|
||||||
|
m_searchThread = NULL;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ResetResults();
|
||||||
|
|
||||||
m_searchChanged = false;
|
m_searchChanged = false;
|
||||||
}
|
}
|
||||||
@ -101,75 +124,35 @@ void wxZRColaCharSelect::OnSearchText(wxCommandEvent& event)
|
|||||||
{
|
{
|
||||||
event.Skip();
|
event.Skip();
|
||||||
|
|
||||||
m_timerSearch.Stop();
|
|
||||||
m_searchChanged = true;
|
m_searchChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wxZRColaCharSelect::OnSearchEnter(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
event.Skip();
|
|
||||||
|
|
||||||
m_timerSearch.Stop();
|
|
||||||
wxTimerEvent e(m_timerSearch);
|
|
||||||
GetEventHandler()->ProcessEvent(e);
|
|
||||||
|
|
||||||
m_searchChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wxZRColaCharSelect::OnSearchTimer(wxTimerEvent& event)
|
|
||||||
{
|
|
||||||
wxString val(m_search->GetValue());
|
|
||||||
if (!val.IsEmpty()) {
|
|
||||||
ZRColaApp *app = (ZRColaApp*)wxTheApp;
|
|
||||||
std::map<wchar_t, unsigned long> hits;
|
|
||||||
std::set<ZRCola::chrcatid_t> cats;
|
|
||||||
|
|
||||||
// Select categories.
|
|
||||||
for (size_t i = 0, n = app->m_cc_db.idxRnk.size(); i < n; i++) {
|
|
||||||
const ZRCola::chrcat_db::chrcat &cc = app->m_cc_db.idxRnk[i];
|
|
||||||
if (m_categories->IsChecked(i))
|
|
||||||
cats.insert(cc.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Search by indexes and merge results.
|
|
||||||
std::map<wchar_t, unsigned long> hits_sub;
|
|
||||||
app->m_chr_db.Search(val.c_str(), cats, hits, hits_sub);
|
|
||||||
for (std::map<wchar_t, unsigned long>::const_iterator i = hits_sub.cbegin(), i_end = hits_sub.cend(); i != i_end; ++i) {
|
|
||||||
std::map<wchar_t, unsigned long>::iterator idx = hits.find(i->first);
|
|
||||||
if (idx == hits.end())
|
|
||||||
hits.insert(std::make_pair(i->first, i->second / 4));
|
|
||||||
else
|
|
||||||
idx->second += i->second / 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now sort the characters by rank.
|
|
||||||
std::vector< std::pair<unsigned long, wchar_t> > hits2;
|
|
||||||
hits2.reserve(hits.size());
|
|
||||||
for (std::map<wchar_t, unsigned long>::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i)
|
|
||||||
hits2.push_back(std::make_pair(i->second, i->first));
|
|
||||||
std::qsort(hits2.data(), hits2.size(), sizeof(std::pair<unsigned long, wchar_t>), compare_hits);
|
|
||||||
|
|
||||||
// Display results.
|
|
||||||
wxString chars;
|
|
||||||
chars.reserve(hits2.size());
|
|
||||||
for (std::vector< std::pair<unsigned long, wchar_t> >::const_iterator i = hits2.cbegin(), i_end = hits2.cend(); i != i_end; ++i)
|
|
||||||
chars += i->second;
|
|
||||||
m_gridResults->SetCharacters(chars);
|
|
||||||
} else
|
|
||||||
ResetResults();
|
|
||||||
|
|
||||||
m_gridResults->Scroll(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wxZRColaCharSelect::OnCategoriesToggle(wxCommandEvent& event)
|
void wxZRColaCharSelect::OnCategoriesToggle(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
m_timerSearch.Stop();
|
event.Skip();
|
||||||
m_timerSearch.Start(500, true);
|
|
||||||
|
m_searchChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wxZRColaCharSelect::OnSearchComplete(wxThreadEvent& event)
|
||||||
|
{
|
||||||
|
event.Skip();
|
||||||
|
|
||||||
|
if (m_searchThread) {
|
||||||
|
// Display results.
|
||||||
|
wxString chars;
|
||||||
|
chars.reserve(m_searchThread->m_hits.size());
|
||||||
|
for (std::vector< std::pair<unsigned long, wchar_t> >::const_iterator i = m_searchThread->m_hits.cbegin(), i_end = m_searchThread->m_hits.cend(); i != i_end; ++i)
|
||||||
|
chars += i->second;
|
||||||
|
m_gridResults->SetCharacters(chars);
|
||||||
|
|
||||||
|
m_searchThread->Delete();
|
||||||
|
m_searchThread = NULL;
|
||||||
|
|
||||||
|
m_gridResults->Scroll(0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -305,6 +288,74 @@ void wxZRColaCharSelect::ResetResults()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxZRColaCharSelect::SearchThread::SearchThread(wxZRColaCharSelect *parent) :
|
||||||
|
m_parent(parent),
|
||||||
|
wxThread(wxTHREAD_JOINABLE)
|
||||||
|
{
|
||||||
|
//// This is a worker thread. Set priority between minimal and normal.
|
||||||
|
//SetPriority((wxPRIORITY_MIN + wxPRIORITY_DEFAULT) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxThread::ExitCode wxZRColaCharSelect::SearchThread::Entry()
|
||||||
|
{
|
||||||
|
ZRColaApp *app = (ZRColaApp*)wxTheApp;
|
||||||
|
std::map<wchar_t, unsigned long> hits;
|
||||||
|
|
||||||
|
if (TestDestroy()) return (wxThread::ExitCode)1;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Search by indexes and merge results.
|
||||||
|
std::map<wchar_t, unsigned long> hits_sub;
|
||||||
|
if (!app->m_chr_db.Search(m_search.c_str(), m_cats, hits, hits_sub, TestDestroyS, this)) return (wxThread::ExitCode)1;
|
||||||
|
for (std::map<wchar_t, unsigned long>::const_iterator i = hits_sub.cbegin(), i_end = hits_sub.cend(); i != i_end; ++i) {
|
||||||
|
if (TestDestroy()) return (wxThread::ExitCode)1;
|
||||||
|
std::map<wchar_t, unsigned long>::iterator idx = hits.find(i->first);
|
||||||
|
if (idx == hits.end())
|
||||||
|
hits.insert(std::make_pair(i->first, i->second / 4));
|
||||||
|
else
|
||||||
|
idx->second += i->second / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now sort the characters by rank.
|
||||||
|
m_hits.reserve(hits.size());
|
||||||
|
for (std::map<wchar_t, unsigned long>::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i) {
|
||||||
|
if (TestDestroy()) return (wxThread::ExitCode)1;
|
||||||
|
m_hits.push_back(std::make_pair(i->second, i->first));
|
||||||
|
}
|
||||||
|
std::qsort(m_hits.data(), m_hits.size(), sizeof(std::pair<unsigned long, wchar_t>), CompareHits);
|
||||||
|
|
||||||
|
// Signal the event handler that this thread is going to be destroyed.
|
||||||
|
// NOTE: here we assume that using the m_parent pointer is safe,
|
||||||
|
// (in this case this is assured by the wxZRColaCharSelect destructor)
|
||||||
|
wxQueueEvent(m_parent, new wxThreadEvent(wxEVT_SEARCH_COMPLETE));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int __cdecl wxZRColaCharSelect::SearchThread::CompareHits(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const std::pair<unsigned long, wchar_t> *_a = (const std::pair<unsigned long, wchar_t>*)a;
|
||||||
|
const std::pair<unsigned long, wchar_t> *_b = (const std::pair<unsigned long, wchar_t>*)b;
|
||||||
|
|
||||||
|
if (_a->first > _b->first) return -1;
|
||||||
|
else if (_a->first < _b->first) return 1;
|
||||||
|
|
||||||
|
if (_a->second < _b->second) return -1;
|
||||||
|
else if (_a->second > _b->second) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool __cdecl wxZRColaCharSelect::SearchThread::TestDestroyS(void *cookie)
|
||||||
|
{
|
||||||
|
return static_cast<wxZRColaCharSelect::SearchThread*>(cookie)->TestDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// wxPersistentZRColaCharSelect
|
// wxPersistentZRColaCharSelect
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -30,9 +30,14 @@ class wxZRColaCharSelect;
|
|||||||
#include <zrcola/character.h>
|
#include <zrcola/character.h>
|
||||||
#include <wxex/valhex.h>
|
#include <wxex/valhex.h>
|
||||||
#include <wxex/persist/dialog.h>
|
#include <wxex/persist/dialog.h>
|
||||||
|
#include <wx/event.h>
|
||||||
|
#include <wx/thread.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
wxDECLARE_EVENT(wxEVT_SEARCH_COMPLETE, wxThreadEvent);
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// ZRCola character select dialog
|
/// ZRCola character select dialog
|
||||||
///
|
///
|
||||||
@ -40,15 +45,16 @@ class wxZRColaCharSelect : public wxZRColaCharSelectBase
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxZRColaCharSelect(wxWindow* parent);
|
wxZRColaCharSelect(wxWindow* parent);
|
||||||
|
virtual ~wxZRColaCharSelect();
|
||||||
|
|
||||||
friend class wxPersistentZRColaCharSelect; // Allow saving/restoring window state.
|
friend class wxPersistentZRColaCharSelect; // Allow saving/restoring window state.
|
||||||
|
friend class SearchThread; // For search thread back-notifications
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void OnIdle(wxIdleEvent& event);
|
virtual void OnIdle(wxIdleEvent& event);
|
||||||
virtual void OnSearchText(wxCommandEvent& event);
|
virtual void OnSearchText(wxCommandEvent& event);
|
||||||
virtual void OnSearchEnter(wxCommandEvent& event);
|
|
||||||
virtual void OnSearchTimer(wxTimerEvent& event);
|
|
||||||
virtual void OnCategoriesToggle(wxCommandEvent& event);
|
virtual void OnCategoriesToggle(wxCommandEvent& event);
|
||||||
|
void OnSearchComplete(wxThreadEvent& event);
|
||||||
virtual void OnResultSelectCell(wxGridEvent& event);
|
virtual void OnResultSelectCell(wxGridEvent& event);
|
||||||
virtual void OnResultCellDClick(wxGridEvent& event);
|
virtual void OnResultCellDClick(wxGridEvent& event);
|
||||||
virtual void OnResultsKeyDown(wxKeyEvent& event);
|
virtual void OnResultsKeyDown(wxKeyEvent& event);
|
||||||
@ -65,12 +71,36 @@ public:
|
|||||||
wchar_t m_char; ///< Currently selected character (0 when none)
|
wchar_t m_char; ///< Currently selected character (0 when none)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_searchChanged; ///< Did Search field change?
|
bool m_searchChanged; ///< Did Search field or category selection change?
|
||||||
std::map<ZRCola::chrcatid_t, int> m_ccOrder; ///< Character category order
|
std::map<ZRCola::chrcatid_t, int> m_ccOrder; ///< Character category order
|
||||||
bool m_unicodeChanged; ///< Did Unicode field change?
|
bool m_unicodeChanged; ///< Did Unicode field change?
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Search worker thread
|
||||||
|
///
|
||||||
|
class SearchThread : public wxThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SearchThread(wxZRColaCharSelect *parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ExitCode Entry();
|
||||||
|
static int __cdecl CompareHits(const void *a, const void *b);
|
||||||
|
static bool __cdecl TestDestroyS(void *cookie);
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::wstring m_search; ///< Search phrase
|
||||||
|
std::set<ZRCola::chrcatid_t> m_cats; ///< Search categories
|
||||||
|
std::vector< std::pair<unsigned long, wchar_t> > m_hits; ///< Search results
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxZRColaCharSelect *m_parent; ///< Thread owner
|
||||||
|
} *m_searchThread; ///< Search thread
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Supports saving/restoring wxZRColaCharSelect state
|
/// Supports saving/restoring wxZRColaCharSelect state
|
||||||
///
|
///
|
||||||
|
@ -416,7 +416,7 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
|
|||||||
wxStaticBoxSizer* sbSizerBrowse;
|
wxStaticBoxSizer* sbSizerBrowse;
|
||||||
sbSizerBrowse = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("&Browse") ), wxVERTICAL );
|
sbSizerBrowse = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("&Browse") ), wxVERTICAL );
|
||||||
|
|
||||||
m_search = new wxSearchCtrl( sbSizerBrowse->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
|
m_search = new wxSearchCtrl( sbSizerBrowse->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
#ifndef __WXMAC__
|
#ifndef __WXMAC__
|
||||||
m_search->ShowSearchButton( true );
|
m_search->ShowSearchButton( true );
|
||||||
#endif
|
#endif
|
||||||
@ -610,12 +610,10 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
|
|||||||
this->SetSizer( bSizerContent );
|
this->SetSizer( bSizerContent );
|
||||||
this->Layout();
|
this->Layout();
|
||||||
bSizerContent->Fit( this );
|
bSizerContent->Fit( this );
|
||||||
m_timerSearch.SetOwner( this, wxID_TIMER_SEARCH );
|
|
||||||
|
|
||||||
// Connect Events
|
// Connect Events
|
||||||
this->Connect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) );
|
this->Connect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) );
|
||||||
m_search->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this );
|
m_search->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this );
|
||||||
m_search->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchEnter ), NULL, this );
|
|
||||||
m_categories->Connect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this );
|
m_categories->Connect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this );
|
||||||
m_gridResults->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this );
|
m_gridResults->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this );
|
||||||
m_gridResults->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this );
|
m_gridResults->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this );
|
||||||
@ -626,7 +624,6 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
|
|||||||
m_unicode->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this );
|
m_unicode->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this );
|
||||||
m_gridRelated->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this );
|
m_gridRelated->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this );
|
||||||
m_sdbSizerButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this );
|
m_sdbSizerButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this );
|
||||||
this->Connect( wxID_TIMER_SEARCH, wxEVT_TIMER, wxTimerEventHandler( wxZRColaCharSelectBase::OnSearchTimer ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
|
wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
|
||||||
@ -634,7 +631,6 @@ wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
|
|||||||
// Disconnect Events
|
// Disconnect Events
|
||||||
this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) );
|
this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) );
|
||||||
m_search->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this );
|
m_search->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this );
|
||||||
m_search->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchEnter ), NULL, this );
|
|
||||||
m_categories->Disconnect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this );
|
m_categories->Disconnect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this );
|
||||||
m_gridResults->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this );
|
m_gridResults->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this );
|
||||||
m_gridResults->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this );
|
m_gridResults->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this );
|
||||||
@ -645,6 +641,5 @@ wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
|
|||||||
m_unicode->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this );
|
m_unicode->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this );
|
||||||
m_gridRelated->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this );
|
m_gridRelated->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this );
|
||||||
m_sdbSizerButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this );
|
m_sdbSizerButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this );
|
||||||
this->Disconnect( wxID_TIMER_SEARCH, wxEVT_TIMER, wxTimerEventHandler( wxZRColaCharSelectBase::OnSearchTimer ) );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -186,11 +186,6 @@ class wxZRColaCharSelectBase : public wxDialog
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum
|
|
||||||
{
|
|
||||||
wxID_TIMER_SEARCH = 1000
|
|
||||||
};
|
|
||||||
|
|
||||||
wxSearchCtrl* m_search;
|
wxSearchCtrl* m_search;
|
||||||
wxCheckListBox* m_categories;
|
wxCheckListBox* m_categories;
|
||||||
wxZRColaCharGrid* m_gridResults;
|
wxZRColaCharGrid* m_gridResults;
|
||||||
@ -203,12 +198,10 @@ class wxZRColaCharSelectBase : public wxDialog
|
|||||||
wxStdDialogButtonSizer* m_sdbSizerButtons;
|
wxStdDialogButtonSizer* m_sdbSizerButtons;
|
||||||
wxButton* m_sdbSizerButtonsOK;
|
wxButton* m_sdbSizerButtonsOK;
|
||||||
wxButton* m_sdbSizerButtonsCancel;
|
wxButton* m_sdbSizerButtonsCancel;
|
||||||
wxTimer m_timerSearch;
|
|
||||||
|
|
||||||
// Virtual event handlers, overide them in your derived class
|
// Virtual event handlers, overide them in your derived class
|
||||||
virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); }
|
virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); }
|
||||||
virtual void OnSearchText( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnSearchText( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnSearchEnter( wxCommandEvent& event ) { event.Skip(); }
|
|
||||||
virtual void OnCategoriesToggle( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnCategoriesToggle( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnResultCellDClick( wxGridEvent& event ) { event.Skip(); }
|
virtual void OnResultCellDClick( wxGridEvent& event ) { event.Skip(); }
|
||||||
virtual void OnResultSelectCell( wxGridEvent& event ) { event.Skip(); }
|
virtual void OnResultSelectCell( wxGridEvent& event ) { event.Skip(); }
|
||||||
@ -219,7 +212,6 @@ class wxZRColaCharSelectBase : public wxDialog
|
|||||||
virtual void OnUnicodeText( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnUnicodeText( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnRelatedSelectCell( wxGridEvent& event ) { event.Skip(); }
|
virtual void OnRelatedSelectCell( wxGridEvent& event ) { event.Skip(); }
|
||||||
virtual void OnOKButtonClick( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnOKButtonClick( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnSearchTimer( wxTimerEvent& event ) { event.Skip(); }
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -234,8 +234,10 @@ namespace ZRCola {
|
|||||||
/// \param[in ] cats Set of categories, character must be a part of
|
/// \param[in ] cats Set of categories, character must be a part of
|
||||||
/// \param[inout] hits (character, count) map to append full-word hits to
|
/// \param[inout] hits (character, count) map to append full-word hits to
|
||||||
/// \param[inout] hits_sub (character, count) map to append partial-word hits to
|
/// \param[inout] hits_sub (character, count) map to append partial-word hits to
|
||||||
|
/// \param[in] fn_abort Pointer to function to periodically test for search cancellation
|
||||||
|
/// \param[in] cookie Cookie for \p fn_abort call
|
||||||
///
|
///
|
||||||
void Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub) const;
|
bool Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie) = NULL, _In_opt_ void *cookie = NULL) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Get character category
|
/// Get character category
|
||||||
|
@ -20,15 +20,17 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
|
||||||
void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub) const
|
bool ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie), _In_opt_ void *cookie) const
|
||||||
{
|
{
|
||||||
assert(str);
|
assert(str);
|
||||||
|
|
||||||
while (*str) {
|
while (*str) {
|
||||||
|
if (fn_abort && fn_abort(cookie)) return false;
|
||||||
|
|
||||||
// Skip white space.
|
// Skip white space.
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (*str == 0)
|
if (*str == 0)
|
||||||
return;
|
return true;
|
||||||
else if (!iswspace(*str))
|
else if (!iswspace(*str))
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
@ -59,15 +61,20 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!term.empty()) {
|
if (!term.empty()) {
|
||||||
|
if (fn_abort && fn_abort(cookie)) return false;
|
||||||
|
|
||||||
// Find the term.
|
// Find the term.
|
||||||
std::transform(term.begin(), term.end(), term.begin(), std::towlower);
|
std::transform(term.begin(), term.end(), term.begin(), std::towlower);
|
||||||
|
|
||||||
|
if (fn_abort && fn_abort(cookie)) return false;
|
||||||
|
|
||||||
const wchar_t *data;
|
const wchar_t *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (idxDsc.find(term.c_str(), term.size(), &data, &len)) {
|
if (idxDsc.find(term.c_str(), term.size(), &data, &len)) {
|
||||||
// The term was found.
|
// The term was found.
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
if (fn_abort && fn_abort(cookie)) return false;
|
||||||
wchar_t c = data[i];
|
wchar_t c = data[i];
|
||||||
if (cats.find(GetCharCat(c)) != cats.end()) {
|
if (cats.find(GetCharCat(c)) != cats.end()) {
|
||||||
std::map<wchar_t, unsigned long>::iterator idx = hits.find(c);
|
std::map<wchar_t, unsigned long>::iterator idx = hits.find(c);
|
||||||
@ -85,6 +92,7 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
|
|||||||
if (idxDscSub.find(term.c_str(), term.size(), &data, &len)) {
|
if (idxDscSub.find(term.c_str(), term.size(), &data, &len)) {
|
||||||
// The term was found in the sub-term index.
|
// The term was found in the sub-term index.
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
if (fn_abort && fn_abort(cookie)) return false;
|
||||||
wchar_t c = data[i];
|
wchar_t c = data[i];
|
||||||
if (cats.find(GetCharCat(c)) != cats.end()) {
|
if (cats.find(GetCharCat(c)) != cats.end()) {
|
||||||
std::map<wchar_t, unsigned long>::iterator idx = hits_sub.find(c);
|
std::map<wchar_t, unsigned long>::iterator idx = hits_sub.find(c);
|
||||||
@ -100,4 +108,6 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user