1 /***************************************************************
2  * Name:      ThreadSearchView
3  * Purpose:   This class implements the panel that is added to
4  *            Code::Blocks Message notebook or C::B layout.
5  * Author:    Jerome ANTOINE
6  * Created:   2007-10-08
7  * Copyright: Jerome ANTOINE
8  * License:   GPL
9  **************************************************************/
10 
11 #include "sdk.h"
12 #include <wx/bitmap.h>
13 #include <wx/bmpbuttn.h>
14 #include <wx/statline.h>
15 #ifndef CB_PRECOMP
16     #include <wx/combobox.h>
17     #include <wx/menu.h>
18     #include <wx/sizer.h>
19     #include <wx/splitter.h>
20     #include <wx/statbox.h>
21     #include <wx/stattext.h>
22     #include <wx/settings.h>
23     #include <wx/toolbar.h>
24 
25     #include "cbeditor.h"
26     #include "configmanager.h"
27     #include "editorcolourset.h"
28     #include "infowindow.h"
29     #include "logmanager.h"
30 #endif
31 
32 #include "cbstyledtextctrl.h"
33 #include "encodingdetector.h"
34 #include "SearchInPanel.h"
35 #include "DirectoryParamsPanel.h"
36 #include "ThreadSearch.h"
37 #include "ThreadSearchView.h"
38 #include "ThreadSearchEvent.h"
39 #include "ThreadSearchThread.h"
40 #include "ThreadSearchFindData.h"
41 #include "ThreadSearchCommon.h"
42 #include "ThreadSearchConfPanel.h"
43 #include "ThreadSearchControlIds.h"
44 #include "wx/tglbtn.h"
45 
46 
47 // Max number of items in search history combo box
48 const unsigned int MAX_NB_SEARCH_ITEMS = 20;
49 
50 // Timer value for events handling (events sent by worker thread)
51 const          int TIMER_PERIOD        = 100;
52 
53 
ThreadSearchView(ThreadSearch & threadSearchPlugin)54 ThreadSearchView::ThreadSearchView(ThreadSearch& threadSearchPlugin)
55                  :wxPanel(Manager::Get()->GetAppWindow())
56                  ,m_ThreadSearchPlugin(threadSearchPlugin)
57                  ,m_Timer(this, controlIDs.Get(ControlIDs::idTmrListCtrlUpdate))
58                  ,m_StoppingThread(0)
59 {
60     m_pFindThread = NULL;
61     m_pToolBar    = NULL;
62     const wxString &prefix = GetImagePrefix(false, Manager::Get()->GetAppWindow());
63     const double scaleFactor = cbGetContentScaleFactor(*Manager::Get()->GetAppWindow());
64 
65     // begin wxGlade: ThreadSearchView::ThreadSearchView
66     m_pSplitter = new wxSplitterWindow(this, -1, wxDefaultPosition, wxSize(1,1), wxSP_3D|wxSP_BORDER|wxSP_PERMIT_UNSPLIT);
67     m_pPnlListLog = new wxPanel(m_pSplitter, -1, wxDefaultPosition, wxSize(1,1));
68     m_pPnlPreview = new wxPanel(m_pSplitter, -1, wxDefaultPosition, wxSize(1,1));
69     m_pSizerSearchDirItems_staticbox = new wxStaticBox(this, -1, _("Directory parameters"));
70     const wxString m_pCboSearchExpr_choices[] = {
71 
72     };
73     m_pCboSearchExpr = new wxComboBox(this, controlIDs.Get(ControlIDs::idCboSearchExpr), wxEmptyString,
74                                       wxDefaultPosition, wxDefaultSize, 0, m_pCboSearchExpr_choices,
75                                       wxCB_DROPDOWN|wxTE_PROCESS_ENTER);
76     m_pBtnSearch = new wxBitmapButton(this, controlIDs.Get(ControlIDs::idBtnSearch),
77                                       cbLoadBitmapScaled(prefix + wxT("findf.png"),
78                                                          wxBITMAP_TYPE_PNG, scaleFactor),
79                                       wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
80     m_pBtnOptions = new wxBitmapButton(this, controlIDs.Get(ControlIDs::idBtnOptions),
81                                        cbLoadBitmapScaled(prefix + wxT("options.png"),
82                                                           wxBITMAP_TYPE_PNG, scaleFactor),
83                                        wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
84     m_pStaticLine1 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
85     m_pStaTxtSearchIn = new wxStaticText(this, -1, _("Search in "));
86     m_pPnlSearchIn = new SearchInPanel(this, -1);
87     m_pStaticLine2 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
88     m_pBtnShowDirItems = new wxBitmapButton(this, controlIDs.Get(ControlIDs::idBtnShowDirItemsClick),
89                                             cbLoadBitmapScaled(prefix + wxT("showdir.png"),
90                                                                wxBITMAP_TYPE_PNG, scaleFactor),
91                                             wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
92     m_pPnlDirParams = new DirectoryParamsPanel(&threadSearchPlugin.GetFindData(), this, -1);
93     m_pSearchPreview = new cbStyledTextCtrl(m_pPnlPreview, wxID_ANY, wxDefaultPosition, wxSize(1,1));
94     m_pLogger = ThreadSearchLoggerBase::BuildThreadSearchLoggerBase(*this, m_ThreadSearchPlugin,
95                                                                     m_ThreadSearchPlugin.GetLoggerType(),
96                                                                     m_ThreadSearchPlugin.GetFileSorting(),
97                                                                     m_pPnlListLog,
98                                                                     controlIDs.Get(ControlIDs::idWndLogger));
99 
100     set_properties();
101     do_layout();
102     // end wxGlade
103 
104     // Dynamic event connections.
105     // Static events table (BEGIN_EVENT_TABLE) doesn't work for all events
106     long id = m_pSearchPreview->GetId();
107     Connect(id, wxEVT_SCI_MARGINCLICK,
108             (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
109             &ThreadSearchView::OnMarginClick);
110 
111     Connect(id, wxEVT_CONTEXT_MENU,
112             (wxObjectEventFunction) (wxEventFunction) (wxContextMenuEventFunction)
113             &ThreadSearchView::OnContextMenu);
114 
115     Connect(wxEVT_THREAD_SEARCH_ERROR,
116             (wxObjectEventFunction)&ThreadSearchView::OnThreadSearchErrorEvent);
117 }
118 
119 
~ThreadSearchView()120 ThreadSearchView::~ThreadSearchView()
121 {
122     if ( m_pFindThread != NULL )
123     {
124         StopThread();
125     }
126 
127     // I don't know if it is necessay to remove event connections
128     // so I do it myself
129     long id = m_pSearchPreview->GetId();
130     Disconnect(id, wxEVT_SCI_MARGINCLICK,
131             (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
132             &ThreadSearchView::OnMarginClick);
133 
134     Disconnect(id, wxEVT_CONTEXT_MENU,
135             (wxObjectEventFunction) (wxEventFunction) (wxContextMenuEventFunction)
136             &ThreadSearchView::OnContextMenu);
137 
138     Disconnect(wxEVT_THREAD_SEARCH_ERROR,
139             (wxObjectEventFunction)&ThreadSearchView::OnThreadSearchErrorEvent);
140 
141     m_ThreadSearchPlugin.OnThreadSearchViewDestruction();
142 
143     delete m_pLogger;
144     m_pLogger = NULL;
145 }
146 
147 // As SearchInPanel and DirectoryParamsPanel are generic, their
148 // events are managed by parent ie this ThreadSearchView class.
149 BEGIN_EVENT_TABLE(ThreadSearchView, wxPanel)
150     // begin wxGlade: ThreadSearchView::event_table
151     EVT_TEXT_ENTER(controlIDs.Get(ControlIDs::idCboSearchExpr), ThreadSearchView::OnCboSearchExprEnter)
152     EVT_TEXT_ENTER(controlIDs.Get(ControlIDs::idSearchDirPath), ThreadSearchView::OnCboSearchExprEnter)
153     EVT_TEXT_ENTER(controlIDs.Get(ControlIDs::idSearchMask), ThreadSearchView::OnCboSearchExprEnter)
154     EVT_BUTTON(controlIDs.Get(ControlIDs::idBtnSearch), ThreadSearchView::OnBtnSearchClick)
155     EVT_BUTTON(controlIDs.Get(ControlIDs::idBtnOptions), ThreadSearchView::OnBtnOptionsClick)
156 
157     EVT_MENU(controlIDs.Get(ControlIDs::idOptionDialog), ThreadSearchView::OnShowOptionsDialog)
158     EVT_MENU(controlIDs.Get(ControlIDs::idOptionWholeWord), ThreadSearchView::OnQuickOptions)
159     EVT_MENU(controlIDs.Get(ControlIDs::idOptionStartWord), ThreadSearchView::OnQuickOptions)
160     EVT_MENU(controlIDs.Get(ControlIDs::idOptionMatchCase), ThreadSearchView::OnQuickOptions)
161     EVT_MENU(controlIDs.Get(ControlIDs::idOptionRegEx), ThreadSearchView::OnQuickOptions)
162 
163     EVT_UPDATE_UI(controlIDs.Get(ControlIDs::idOptionWholeWord), ThreadSearchView::OnQuickOptionsUpdateUI)
164     EVT_UPDATE_UI(controlIDs.Get(ControlIDs::idOptionStartWord), ThreadSearchView::OnQuickOptionsUpdateUI)
165     EVT_UPDATE_UI(controlIDs.Get(ControlIDs::idOptionMatchCase), ThreadSearchView::OnQuickOptionsUpdateUI)
166     EVT_UPDATE_UI(controlIDs.Get(ControlIDs::idOptionRegEx), ThreadSearchView::OnQuickOptionsUpdateUI)
167 
168     EVT_BUTTON(controlIDs.Get(ControlIDs::idBtnShowDirItemsClick), ThreadSearchView::OnBtnShowDirItemsClick)
169     EVT_SPLITTER_DCLICK(-1, ThreadSearchView::OnSplitterDoubleClick)
170     // end wxGlade
171 
172     EVT_TOGGLEBUTTON(controlIDs.Get(ControlIDs::idBtnSearchOpenFiles),      ThreadSearchView::OnBtnSearchOpenFiles)
173     EVT_TOGGLEBUTTON(controlIDs.Get(ControlIDs::idBtnSearchTargetFiles),    ThreadSearchView::OnBtnSearchTargetFiles)
174     EVT_TOGGLEBUTTON(controlIDs.Get(ControlIDs::idBtnSearchProjectFiles),   ThreadSearchView::OnBtnSearchProjectFiles)
175     EVT_TOGGLEBUTTON(controlIDs.Get(ControlIDs::idBtnSearchWorkspaceFiles), ThreadSearchView::OnBtnSearchWorkspaceFiles)
176     EVT_TOGGLEBUTTON(controlIDs.Get(ControlIDs::idBtnSearchDirectoryFiles), ThreadSearchView::OnBtnSearchDirectoryFiles)
177 
178     EVT_TIMER(controlIDs.Get(ControlIDs::idTmrListCtrlUpdate),          ThreadSearchView::OnTmrListCtrlUpdate)
179 END_EVENT_TABLE();
180 
181 
OnThreadSearchErrorEvent(const ThreadSearchEvent & event)182 void ThreadSearchView::OnThreadSearchErrorEvent(const ThreadSearchEvent& event)
183 {
184     Manager::Get()->GetLogManager()->Log(F(_T("ThreadSearch: %s"), event.GetString().wx_str()));
185     InfoWindow::Display(_("Thread Search Error"), event.GetString());
186 }
187 
OnCboSearchExprEnter(wxCommandEvent &)188 void ThreadSearchView::OnCboSearchExprEnter(wxCommandEvent &/*event*/)
189 {
190     // Event handler used when user clicks on enter after typing
191     // in combo box text control.
192     // Runs a multi threaded search.
193     ThreadSearchFindData findData = m_ThreadSearchPlugin.GetFindData();
194     findData.SetFindText(m_pCboSearchExpr->GetValue());
195     ThreadedSearch(findData);
196 }
197 
198 
OnBtnSearchClick(wxCommandEvent &)199 void ThreadSearchView::OnBtnSearchClick(wxCommandEvent &/*event*/)
200 {
201     // User clicked on Search/Cancel
202     // m_ThreadSearchEventsArray is shared by two threads, we
203     // use m_MutexSearchEventsArray to have a safe access.
204     // As button action depends on m_ThreadSearchEventsArray,
205     // we lock the mutex to process it correctly.
206     if ( m_MutexSearchEventsArray.Lock() == wxMUTEX_NO_ERROR )
207     {
208         int nbEvents = m_ThreadSearchEventsArray.GetCount();
209         m_MutexSearchEventsArray.Unlock();
210         if ( m_pFindThread != NULL )
211         {
212             // A threaded search is running...
213             UpdateSearchButtons(false);
214             StopThread();
215         }
216         else if ( nbEvents > 0 )
217         {
218             // A threaded search has run but the events array is
219             // not completely processed...
220             UpdateSearchButtons(false);
221             if ( ClearThreadSearchEventsArray() == false )
222             {
223                 cbMessageBox(_("Failed to clear events array."), _("Error"), wxICON_ERROR);
224             }
225         }
226         else
227         {
228             // We start the thread search
229             ThreadSearchFindData findData = m_ThreadSearchPlugin.GetFindData();
230             findData.SetFindText(m_pCboSearchExpr->GetValue());
231             ThreadedSearch(findData);
232         }
233     }
234 }
235 
236 
OnBtnOptionsClick(wxCommandEvent &)237 void ThreadSearchView::OnBtnOptionsClick(wxCommandEvent &/*event*/)
238 {
239     wxMenu menu;
240     menu.Append(controlIDs.Get(ControlIDs::idOptionDialog), _("Options"), _("Shows the options dialog"));
241     menu.AppendSeparator();
242     menu.AppendCheckItem(controlIDs.Get(ControlIDs::idOptionWholeWord),
243                          _("Whole word"), _("Search text matches only whole words"));
244     menu.AppendCheckItem(controlIDs.Get(ControlIDs::idOptionStartWord),
245                          _("Start word"), _("Matches only word starting with search expression"));
246     menu.AppendCheckItem(controlIDs.Get(ControlIDs::idOptionMatchCase), _("Match case"), _("Case sensitive search."));
247     menu.AppendCheckItem(controlIDs.Get(ControlIDs::idOptionRegEx),
248                          _("Regular expression"), _("Search expression is a regular expression"));
249 
250     PopupMenu(&menu);
251 }
252 
OnShowOptionsDialog(wxCommandEvent &)253 void ThreadSearchView::OnShowOptionsDialog(wxCommandEvent &/*event*/)
254 {
255     // Displays a dialog box with a ThreadSearchConfPanel.
256     // All parameters can be set on this dialog.
257     // It is the same as doing 'Settings/environment/Thread search'
258     // Settings are updated by the cbConfigurationDialog
259     cbConfigurationDialog* pDlg       = new cbConfigurationDialog(Manager::Get()->GetAppWindow(), -1, _("Options"));
260     ThreadSearchConfPanel* pConfPanel = new ThreadSearchConfPanel(m_ThreadSearchPlugin, pDlg);
261 
262     pDlg->AttachConfigurationPanel(pConfPanel);
263     pDlg->ShowModal();
264     pDlg->Destroy();
265 }
266 
OnQuickOptions(wxCommandEvent & event)267 void ThreadSearchView::OnQuickOptions(wxCommandEvent &event)
268 {
269     ThreadSearchFindData findData = m_ThreadSearchPlugin.GetFindData();
270     bool hasChange = false;
271     if (event.GetId() == controlIDs.Get(ControlIDs::idOptionWholeWord))
272     {
273         findData.SetMatchWord(event.IsChecked());
274         hasChange = true;
275     }
276     else if (event.GetId() == controlIDs.Get(ControlIDs::idOptionStartWord))
277     {
278         findData.SetStartWord(event.IsChecked());
279         hasChange = true;
280     }
281     else if (event.GetId() == controlIDs.Get(ControlIDs::idOptionMatchCase))
282     {
283         findData.SetMatchCase(event.IsChecked());
284         hasChange = true;
285     }
286     else if (event.GetId() == controlIDs.Get(ControlIDs::idOptionRegEx))
287     {
288         findData.SetRegEx(event.IsChecked());
289         hasChange = true;
290     }
291     if (hasChange)
292     {
293         m_ThreadSearchPlugin.SetFindData(findData);
294         UpdateOptionsButtonImage(findData);
295     }
296 }
297 
UpdateOptionsButtonImage(const ThreadSearchFindData & findData)298 void ThreadSearchView::UpdateOptionsButtonImage(const ThreadSearchFindData &findData)
299 {
300     {
301         const wxString name = GetImagePrefix(false, m_pBtnOptions)
302                             + (findData.IsOptionEnabled() ? wxT("optionsactive.png") : wxT("options.png"));
303 
304         const double scaleFactor = cbGetContentScaleFactor(*m_pBtnOptions);
305         wxBitmap bitmap=cbLoadBitmapScaled(name, wxBITMAP_TYPE_PNG, scaleFactor);
306         m_pBtnOptions->SetBitmapLabel(bitmap);
307     }
308 
309     if (m_pToolBar)
310     {
311         const wxString name = GetImagePrefix(true)
312                             + (findData.IsOptionEnabled() ? wxT("optionsactive.png") : wxT("options.png"));
313 
314         const double scaleFactor = cbGetContentScaleFactor(*m_pToolBar);
315         wxBitmap bitmap=cbLoadBitmapScaled(name, wxBITMAP_TYPE_PNG, scaleFactor);
316         m_pToolBar->SetToolNormalBitmap(controlIDs.Get(ControlIDs::idBtnOptions), bitmap);
317     }
318 }
319 
OnQuickOptionsUpdateUI(wxUpdateUIEvent & event)320 void ThreadSearchView::OnQuickOptionsUpdateUI(wxUpdateUIEvent &event)
321 {
322     ThreadSearchFindData &findData = m_ThreadSearchPlugin.GetFindData();
323     if (event.GetId() == controlIDs.Get(ControlIDs::idOptionWholeWord))
324         event.Check(findData.GetMatchWord());
325     else if (event.GetId() == controlIDs.Get(ControlIDs::idOptionStartWord))
326         event.Check(findData.GetStartWord());
327     else if (event.GetId() == controlIDs.Get(ControlIDs::idOptionMatchCase))
328         event.Check(findData.GetMatchCase());
329     else if (event.GetId() == controlIDs.Get(ControlIDs::idOptionRegEx))
330         event.Check(findData.GetRegEx());
331 }
332 
OnBtnShowDirItemsClick(wxCommandEvent & WXUNUSED (event))333 void ThreadSearchView::OnBtnShowDirItemsClick(wxCommandEvent& WXUNUSED(event))
334 {
335     // Shows/Hides directory parameters panel and updates button label.
336     wxSizer* pTopSizer = GetSizer();
337     wxASSERT(m_pSizerSearchDirItems && pTopSizer);
338 
339     bool show = !m_pPnlDirParams->IsShown();
340     m_ThreadSearchPlugin.SetShowDirControls(show);
341 
342     pTopSizer->Show(m_pSizerSearchDirItems, show, true);
343     if ( show == true )
344     {
345         m_pBtnShowDirItems->SetToolTip(_("Hide dir items"));
346     }
347     else
348     {
349         m_pBtnShowDirItems->SetToolTip(_("Show dir items"));
350     }
351     pTopSizer->Layout();
352 }
353 
354 
OnSplitterDoubleClick(wxSplitterEvent &)355 void ThreadSearchView::OnSplitterDoubleClick(wxSplitterEvent &/*event*/)
356 {
357     m_ThreadSearchPlugin.SetShowCodePreview(false);
358     ApplySplitterSettings(false, m_pSplitter->GetSplitMode());
359 
360     // Informs user on how to show code preview later.
361     cbMessageBox(_("To re-enable code preview, check the \"Show code preview editor\" in ThreadSearch options panel."),
362                  _("ThreadSearchInfo"), wxICON_INFORMATION);
363 }
364 
365 // wxGlade: add ThreadSearchView event handlers
366 
367 
set_properties()368 void ThreadSearchView::set_properties()
369 {
370     const wxString &prefix = GetImagePrefix(false, this);
371     const double scaleFactor = cbGetContentScaleFactor(*this);
372 
373     // begin wxGlade: ThreadSearchView::set_properties
374     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
375     m_pCboSearchExpr->SetMinSize(wxSize(180, -1));
376     m_pBtnSearch->SetToolTip(_("Search in files"));
377     m_pBtnSearch->SetBitmapDisabled(cbLoadBitmapScaled(prefix + wxT("findfdisabled.png"),
378                                                        wxBITMAP_TYPE_PNG, scaleFactor));
379     m_pBtnSearch->SetSize(m_pBtnSearch->GetBestSize());
380     m_pBtnOptions->SetToolTip(_("Options"));
381     m_pBtnOptions->SetBitmapDisabled(cbLoadBitmapScaled(prefix + wxT("optionsdisabled.png"),
382                                                         wxBITMAP_TYPE_PNG, scaleFactor));
383     m_pBtnOptions->SetSize(m_pBtnOptions->GetBestSize());
384     m_pBtnShowDirItems->SetToolTip(_("Show dir Items"));
385     m_pBtnShowDirItems->SetBitmapDisabled(cbLoadBitmapScaled(prefix + wxT("showdirdisabled.png"),
386                                                              wxBITMAP_TYPE_PNG, scaleFactor));
387     m_pBtnShowDirItems->SetSize(m_pBtnShowDirItems->GetBestSize());
388     m_pPnlPreview->SetMinSize(wxSize(25, -1));
389     // end wxGlade
390 
391     m_pSearchPreview->SetReadOnly(true);
392 
393     ThreadSearchFindData findData;
394     m_ThreadSearchPlugin.GetFindData(findData);
395 
396     m_pPnlDirParams->SetSearchDirHidden(findData.GetHiddenSearch());
397     m_pPnlDirParams->SetSearchDirRecursively(findData.GetRecursiveSearch());
398     m_pPnlDirParams->SetSearchDirPath(findData.GetSearchPath());
399     m_pPnlDirParams->SetSearchMask(findData.GetSearchMask());
400 
401     m_pPnlSearchIn->SetSearchInOpenFiles(findData.MustSearchInOpenFiles());
402     m_pPnlSearchIn->SetSearchInTargetFiles(findData.MustSearchInTarget());
403     m_pPnlSearchIn->SetSearchInProjectFiles(findData.MustSearchInProject());
404     m_pPnlSearchIn->SetSearchInWorkspaceFiles(findData.MustSearchInWorkspace());
405     m_pPnlSearchIn->SetSearchInDirectory(findData.MustSearchInDirectory());
406 
407     UpdateOptionsButtonImage(findData);
408 }
409 
410 
do_layout()411 void ThreadSearchView::do_layout()
412 {
413 #if wxCHECK_VERSION(3, 0, 0)
414     #define wxADJUST_MINSIZE 0
415 #endif
416     // begin wxGlade: ThreadSearchView::do_layout
417     wxBoxSizer* m_pSizerTop = new wxBoxSizer(wxVERTICAL);
418     wxBoxSizer* m_pSizerSplitter = new wxBoxSizer(wxHORIZONTAL);
419     wxBoxSizer* m_pSizerListLog = new wxBoxSizer(wxHORIZONTAL);
420     wxBoxSizer* m_pSizerSearchPreview = new wxBoxSizer(wxHORIZONTAL);
421     m_pSizerSearchDirItems = new wxStaticBoxSizer(m_pSizerSearchDirItems_staticbox, wxHORIZONTAL);
422     m_pSizerSearchItems = new wxBoxSizer(wxHORIZONTAL);
423     m_pSizerSearchItems->Add(m_pCboSearchExpr, 2, wxALL|wxALIGN_CENTER_VERTICAL|wxADJUST_MINSIZE, 4);
424     m_pSizerSearchItems->Add(m_pBtnSearch, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxADJUST_MINSIZE, 4);
425     m_pSizerSearchItems->Add(m_pBtnOptions, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxADJUST_MINSIZE, 4);
426     m_pSizerSearchItems->Add(m_pStaticLine1, 0, wxLEFT|wxRIGHT|wxEXPAND, 2);
427     m_pSizerSearchItems->Add(m_pStaTxtSearchIn, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxADJUST_MINSIZE, 4);
428     m_pSizerSearchItems->Add(m_pPnlSearchIn, 0, wxALIGN_CENTER_VERTICAL|wxADJUST_MINSIZE, 0);
429     m_pSizerSearchItems->Add(m_pStaticLine2, 0, wxLEFT|wxRIGHT|wxEXPAND, 2);
430     m_pSizerSearchItems->Add(m_pBtnShowDirItems, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxADJUST_MINSIZE, 4);
431     m_pSizerTop->Add(m_pSizerSearchItems, 0, wxEXPAND, 0);
432     m_pSizerSearchDirItems->Add(m_pPnlDirParams, 1, wxALIGN_CENTER_VERTICAL, 0);
433     m_pSizerTop->Add(m_pSizerSearchDirItems, 0, wxBOTTOM|wxEXPAND, 4);
434     m_pSizerSearchPreview->Add(m_pSearchPreview, 1, wxEXPAND|wxADJUST_MINSIZE, 0);
435     m_pPnlPreview->SetAutoLayout(true);
436     m_pPnlPreview->SetSizer(m_pSizerSearchPreview);
437     m_pSizerListLog->Add(m_pLogger->GetWindow(), 1, wxEXPAND|wxFIXED_MINSIZE, 0);
438     m_pPnlListLog->SetAutoLayout(true);
439     m_pPnlListLog->SetSizer(m_pSizerListLog);
440     m_pSplitter->SplitVertically(m_pPnlPreview, m_pPnlListLog);
441     m_pSizerSplitter->Add(m_pSplitter, 1, wxEXPAND|wxADJUST_MINSIZE, 0);
442     m_pSizerTop->Add(m_pSizerSplitter, 1, wxEXPAND, 0);
443     SetAutoLayout(true);
444     SetSizer(m_pSizerTop);
445     m_pSizerTop->Fit(this);
446     m_pSizerTop->SetSizeHints(this);
447     // end wxGlade
448 
449     m_pSplitter->SetMinimumPaneSize(50);
450 }
451 
452 
OnThreadExit()453 void ThreadSearchView::OnThreadExit()
454 {
455     // This method must be called only from ThreadSearchThread::OnExit
456     // because delete is performed in the base class.
457     // We reset the pointer to be sure it is not used.
458     if ( m_pFindThread != NULL )
459     {
460         m_pFindThread = NULL;
461     }
462 
463     if ( m_StoppingThread > 0 )
464     {
465         m_StoppingThread--;
466     }
467 }
468 
469 
ThreadedSearch(const ThreadSearchFindData & aFindData)470 void ThreadSearchView::ThreadedSearch(const ThreadSearchFindData& aFindData)
471 {
472     // We don't search empty patterns
473     if ( aFindData.GetFindText() != wxEmptyString )
474     {
475         ThreadSearchFindData findData(aFindData);
476 
477         // Prepares logger
478         m_pLogger->OnSearchBegin(aFindData);
479 
480         // Two steps thread creation
481         m_pFindThread = new ThreadSearchThread(this, findData);
482         if ( m_pFindThread != NULL )
483         {
484             if ( m_pFindThread->Create() == wxTHREAD_NO_ERROR )
485             {
486                 // Thread execution
487                 if ( m_pFindThread->Run() != wxTHREAD_NO_ERROR )
488                 {
489                     m_pFindThread->Delete();
490                     m_pFindThread = NULL;
491                     cbMessageBox(_("Failed to run search thread"));
492                 }
493                 else
494                 {
495                     // Update combo box search history
496                     AddExpressionToSearchCombos(findData.GetFindText(), findData.GetSearchPath(),
497                                                 findData.GetSearchMask());
498                     UpdateSearchButtons(true, cancel);
499                     EnableControls(false);
500 
501                     // Starts the timer used to managed events sent by m_pFindThread
502                     m_Timer.Start(TIMER_PERIOD, wxTIMER_CONTINUOUS);
503                 }
504             }
505             else
506             {
507                 // Error
508                 m_pFindThread->Delete();
509                 m_pFindThread = NULL;
510                 cbMessageBox(_("Failed to create search thread (2)"));
511             }
512         }
513         else
514         {
515             // Error
516             cbMessageBox(_("Failed to create search thread (1)"));
517         }
518     }
519     else
520     {
521         // Error
522         cbMessageBox(_("Search expression is empty !"));
523     }
524 }
525 
526 
UpdatePreview(const wxString & file,long line)527 bool ThreadSearchView::UpdatePreview(const wxString& file, long line)
528 {
529     bool success(true);
530 
531     if ( line > 0 )
532     {
533         // Line display begins at 1 but line index at 0
534         line--;
535     }
536 
537     // Disable read only
538     m_pSearchPreview->Enable(false);
539     m_pSearchPreview->SetReadOnly(false);
540 
541     // Loads file if different from current loaded
542     wxFileName filename(file);
543     if ( (m_PreviewFilePath != file) || (m_PreviewFileDate != filename.GetModificationTime()) )
544     {
545         ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("editor"));
546 
547         // Remember current file path and modification time
548         m_PreviewFilePath = file;
549         m_PreviewFileDate = filename.GetModificationTime();
550 
551         EncodingDetector enc(m_PreviewFilePath, false);
552         success = enc.IsOK();
553         m_pSearchPreview->SetText(enc.GetWxStr());
554 
555         // Colorize
556         cbEditor::ApplyStyles(m_pSearchPreview);
557         EditorColourSet EdColSet;
558         EdColSet.Apply(EdColSet.GetLanguageForFilename(m_PreviewFilePath), m_pSearchPreview, false,
559                        true);
560 
561         SetFoldingIndicator(mgr->ReadInt(_T("/folding/indicator"), 2));
562         UnderlineFoldedLines(mgr->ReadBool(_T("/folding/underline_folded_line"), true));
563     }
564 
565     if ( success == true )
566     {
567         // Display the selected line
568         int onScreen = m_pSearchPreview->LinesOnScreen() >> 1;
569         m_pSearchPreview->GotoLine(line - onScreen);
570         m_pSearchPreview->GotoLine(line + onScreen);
571         m_pSearchPreview->GotoLine(line);
572         m_pSearchPreview->EnsureVisible(line);
573 
574         int startPos = m_pSearchPreview->PositionFromLine(line);
575         int endPos   = m_pSearchPreview->GetLineEndPosition(line);
576         m_pSearchPreview->SetSelectionVoid(endPos, startPos);
577     }
578 
579     // Enable read only
580     m_pSearchPreview->SetReadOnly(true);
581     m_pSearchPreview->Enable(true);
582 
583     return success;
584 }
585 
586 
OnLoggerClick(const wxString & file,long line)587 void ThreadSearchView::OnLoggerClick(const wxString& file, long line)
588 {
589     // Updates preview editor with selected file at requested line.
590     // We don't check that file changed since search was performed.
591     UpdatePreview(file, line);
592 }
593 
594 
OnLoggerDoubleClick(const wxString & file,long line)595 void ThreadSearchView::OnLoggerDoubleClick(const wxString& file, long line)
596 {
597     cbEditor* ed = Manager::Get()->GetEditorManager()->Open(file);
598     if (!line || !ed)
599         return;
600 
601     line -= 1;
602     ed->Activate();
603 
604     // cbEditor already implements the line centering
605     ed->GotoLine(line);
606 
607     // Show even if line is folded
608     if (cbStyledTextCtrl* control = ed->GetControl()) {
609         control->EnsureVisible(line);
610 
611         wxFocusEvent ev(wxEVT_SET_FOCUS);
612         ev.SetWindow(this);
613         #if wxCHECK_VERSION(3, 0, 0)
614         control->GetEventHandler()->AddPendingEvent(ev);
615         #else
616         control->AddPendingEvent(ev);
617         #endif
618     }
619 }
620 
OnMarginClick(wxScintillaEvent & event)621 void ThreadSearchView::OnMarginClick(wxScintillaEvent& event)
622 {
623     // We handle click on preview editor margin
624     // For now, all is read only; we manage folding but not
625     // breakpoints and bookmarks.
626     switch (event.GetMargin())
627     {
628         case 2: // folding margin
629         {
630             int lineYpix = event.GetPosition();
631             int line = m_pSearchPreview->LineFromPosition(lineYpix);
632 
633             m_pSearchPreview->ToggleFold(line);
634             break;
635         }
636         case 1: // bookmarks and breakpoints margin
637         {
638             // For now I ignore bookmarks and breakpoints
639             /*
640             #define BOOKMARK_MARKER    2
641             int line = m_pSearchPreview->LineFromPosition(event.GetPosition());
642 
643             if ( m_pSearchPreview->MarkerGet(line) & (1 << BOOKMARK_MARKER) )
644             {
645                 m_pSearchPreview->MarkerDelete(line, BOOKMARK_MARKER);
646             }
647             else
648             {
649                 m_pSearchPreview->MarkerAdd(line, BOOKMARK_MARKER);
650             }
651             */
652             break;
653         }
654         default:
655         {
656             break;
657         }
658     }
659 }
660 
661 
OnContextMenu(wxContextMenuEvent & event)662 void ThreadSearchView::OnContextMenu(wxContextMenuEvent& event)
663 {
664     event.StopPropagation();
665 }
666 
667 
AddExpressionToSearchCombos(const wxString & expression,const wxString & path,const wxString & mask)668 void ThreadSearchView::AddExpressionToSearchCombos(const wxString& expression, const wxString& path, const wxString& mask)
669 {
670     // We perform tests on view combo and don't check toolbar one
671     // because their contents are identical
672     // Gets toolbar combo pointer
673     const long id = controlIDs.Get(ControlIDs::idCboSearchExpr);
674     wxComboBox* pToolBarCombo = static_cast<wxComboBox*>(m_pToolBar->FindControl(id));
675 
676     // Updates combos box with new item
677     // Search item index
678     int index = m_pCboSearchExpr->FindString(expression);
679 
680     // Removes item if already in combos box
681     if ( index != wxNOT_FOUND )
682     {
683         m_pCboSearchExpr->Delete(index);
684         pToolBarCombo->Delete(index);
685     }
686 
687     // Removes last item if max nb item is reached
688     if ( m_pCboSearchExpr->GetCount() > MAX_NB_SEARCH_ITEMS )
689     {
690         // Removes last one
691         m_pCboSearchExpr->Delete(m_pCboSearchExpr->GetCount()-1);
692         pToolBarCombo->Delete(pToolBarCombo->GetCount()-1);
693     }
694 
695     // Adds it to combos
696     m_pCboSearchExpr->Insert(expression, 0);
697     m_pCboSearchExpr->SetSelection(0);
698     pToolBarCombo->Insert(expression, 0);
699     pToolBarCombo->SetSelection(0);
700 
701     m_pPnlDirParams->AddExpressionToCombos(path, mask);
702 }
703 
704 
FocusSearchCombo(const wxString & searchWord)705 void ThreadSearchView::FocusSearchCombo(const wxString &searchWord)
706 {
707     if (!searchWord.empty())
708         m_pCboSearchExpr->SetValue(searchWord);
709     m_pCboSearchExpr->SetFocus();
710 }
711 
712 
Update()713 void ThreadSearchView::Update()
714 {
715     ThreadSearchFindData findData;
716     m_ThreadSearchPlugin.GetFindData(findData);
717 
718     m_pPnlSearchIn->SetSearchInOpenFiles     (findData.MustSearchInOpenFiles());
719     m_pPnlSearchIn->SetSearchInTargetFiles   (findData.MustSearchInTarget   ());
720     m_pPnlSearchIn->SetSearchInProjectFiles  (findData.MustSearchInProject  ());
721     m_pPnlSearchIn->SetSearchInWorkspaceFiles(findData.MustSearchInWorkspace());
722     m_pPnlSearchIn->SetSearchInDirectory     (findData.MustSearchInDirectory());
723 
724     m_pPnlDirParams->SetSearchDirHidden      (findData.GetHiddenSearch());
725     m_pPnlDirParams->SetSearchDirRecursively (findData.GetRecursiveSearch());
726     m_pPnlDirParams->SetSearchDirPath        (findData.GetSearchPath());
727     m_pPnlDirParams->SetSearchMask           (findData.GetSearchMask());
728 
729     ShowSearchControls(m_ThreadSearchPlugin.GetShowSearchControls());
730     SetLoggerType(m_ThreadSearchPlugin.GetLoggerType());
731     m_pLogger->Update();
732 
733     ApplySplitterSettings(m_ThreadSearchPlugin.GetShowCodePreview(), m_ThreadSearchPlugin.GetSplitterMode());
734 }
735 
736 
OnBtnSearchOpenFiles(wxCommandEvent & event)737 void ThreadSearchView::OnBtnSearchOpenFiles(wxCommandEvent &event)
738 {
739     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeOpenFiles, m_pPnlSearchIn->GetSearchInOpenFiles());
740     event.Skip();
741 }
742 
743 
OnBtnSearchTargetFiles(wxCommandEvent & event)744 void ThreadSearchView::OnBtnSearchTargetFiles(wxCommandEvent &event)
745 {
746     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeTargetFiles, m_pPnlSearchIn->GetSearchInTargetFiles());
747     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeProjectFiles, false);
748     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeWorkspaceFiles, false);
749     event.Skip();
750 }
751 
752 
OnBtnSearchProjectFiles(wxCommandEvent & event)753 void ThreadSearchView::OnBtnSearchProjectFiles(wxCommandEvent &event)
754 {
755     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeProjectFiles, m_pPnlSearchIn->GetSearchInProjectFiles());
756     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeTargetFiles, false);
757     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeWorkspaceFiles, false);
758     event.Skip();
759 }
760 
761 
OnBtnSearchWorkspaceFiles(wxCommandEvent & event)762 void ThreadSearchView::OnBtnSearchWorkspaceFiles(wxCommandEvent &event)
763 {
764     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeWorkspaceFiles, m_pPnlSearchIn->GetSearchInWorkspaceFiles());
765     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeTargetFiles, false);
766     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeProjectFiles, false);
767     event.Skip();
768 }
769 
770 
OnBtnSearchDirectoryFiles(wxCommandEvent & event)771 void ThreadSearchView::OnBtnSearchDirectoryFiles(wxCommandEvent &event)
772 {
773     m_ThreadSearchPlugin.GetFindData().UpdateSearchScope(ScopeDirectoryFiles, m_pPnlSearchIn->GetSearchInDirectory());
774     event.Skip();
775 }
776 
777 
EnableControls(bool enable)778 void ThreadSearchView::EnableControls(bool enable)
779 {
780     // Used to disable search parameters controls during
781     // threaded search in notebook panel and toolbar.
782     ControlIDs::IDs idsArray[] = {
783         ControlIDs::idBtnDirSelectClick,
784         ControlIDs::idBtnOptions,
785         ControlIDs::idCboSearchExpr,
786         ControlIDs::idChkSearchDirRecurse,
787         ControlIDs::idChkSearchDirHidden,
788         ControlIDs::idBtnSearchOpenFiles,
789         ControlIDs::idBtnSearchTargetFiles,
790         ControlIDs::idBtnSearchProjectFiles,
791         ControlIDs::idBtnSearchWorkspaceFiles,
792         ControlIDs::idBtnSearchDirectoryFiles,
793         ControlIDs::idSearchDirPath,
794         ControlIDs::idSearchMask
795     };
796 
797     ControlIDs::IDs toolBarIdsArray[] = {
798         ControlIDs::idCboSearchExpr
799     };
800 
801     for ( unsigned int i = 0; i < sizeof(idsArray)/sizeof(idsArray[0]); ++i )
802     {
803         wxWindow* pWnd = wxWindow::FindWindow(controlIDs.Get(idsArray[i]));
804         if ( pWnd != 0 )
805         {
806             pWnd->Enable(enable);
807         }
808         else
809         {
810             cbMessageBox(wxString::Format(_("Failed to Enable window (id=%ld)"), idsArray[i]).c_str(),
811                          _("Error"), wxOK|wxICON_ERROR, this);
812         }
813     }
814 
815     for ( unsigned int i = 0; i < sizeof(toolBarIdsArray)/sizeof(toolBarIdsArray[0]); ++i )
816     {
817         m_pToolBar->FindControl(controlIDs.Get(toolBarIdsArray[i]))->Enable(enable);
818     }
819 
820     m_pToolBar->EnableTool(controlIDs.Get(ControlIDs::idBtnOptions), enable);
821     m_pToolBar->Update();
822 }
823 
824 
PostThreadSearchEvent(const ThreadSearchEvent & event)825 void ThreadSearchView::PostThreadSearchEvent(const ThreadSearchEvent& event)
826 {
827     // Clone the worker thread event to the mutex protected m_ThreadSearchEventsArray
828     if ( m_MutexSearchEventsArray.Lock() == wxMUTEX_NO_ERROR )
829     {
830         // Events are handled in ThreadSearchView::OnTmrListCtrlUpdate
831         // ThreadSearchView::OnTmrListCtrlUpdate is called automatically
832         // by m_Timer wxTimer
833         m_ThreadSearchEventsArray.Add(event.Clone());
834         m_MutexSearchEventsArray.Unlock();
835     }
836 }
837 
838 
OnTmrListCtrlUpdate(wxTimerEvent &)839 void ThreadSearchView::OnTmrListCtrlUpdate(wxTimerEvent& /*event*/)
840 {
841     if ( m_MutexSearchEventsArray.Lock() == wxMUTEX_NO_ERROR )
842     {
843         if ( m_ThreadSearchEventsArray.GetCount() > 0 )
844         {
845             ThreadSearchEvent *pEvent = static_cast<ThreadSearchEvent*>(m_ThreadSearchEventsArray[0]);
846             m_pLogger->OnThreadSearchEvent(*pEvent);
847             delete pEvent;
848             m_ThreadSearchEventsArray.RemoveAt(0,1);
849         }
850 
851         if ( (m_ThreadSearchEventsArray.GetCount() == 0) && (m_pFindThread == NULL) )
852         {
853             // Thread search is finished (m_pFindThread == NULL) and m_ThreadSearchEventsArray
854             // is empty (m_ThreadSearchEventsArray.GetCount() == 0).
855             // We stop the timer to spare resources
856             m_Timer.Stop();
857 
858             m_pLogger->OnSearchEnd();
859 
860             // Restores label and enables all search params graphical widgets.
861             UpdateSearchButtons(true, search);
862             EnableControls(true);
863         }
864 
865         m_MutexSearchEventsArray.Unlock();
866     }
867 }
868 
869 
ClearThreadSearchEventsArray()870 bool ThreadSearchView::ClearThreadSearchEventsArray()
871 {
872     bool success = (m_MutexSearchEventsArray.Lock() == wxMUTEX_NO_ERROR);
873     if ( success == true )
874     {
875         size_t i                  = m_ThreadSearchEventsArray.GetCount();
876         ThreadSearchEvent* pEvent = NULL;
877         while ( i != 0 )
878         {
879             pEvent = static_cast<ThreadSearchEvent*>(m_ThreadSearchEventsArray[0]);
880             delete pEvent;
881             m_ThreadSearchEventsArray.RemoveAt(0,1);
882             i--;
883         }
884 
885         m_MutexSearchEventsArray.Unlock();
886     }
887 
888     return success;
889 }
890 
891 
StopThread()892 bool ThreadSearchView::StopThread()
893 {
894     bool success = false;
895     if ( (m_StoppingThread == 0) && (m_pFindThread != NULL) )
896     {
897         // A search thread is running. We stop it.
898         m_StoppingThread++;
899         m_pFindThread->Delete();
900 
901         // We stop the timer responsible for list control update and we wait twice
902         // its period to delete all waiting events (not processed yet)
903         m_Timer.Stop();
904         wxThread::Sleep(2*TIMER_PERIOD);
905 
906         success = ClearThreadSearchEventsArray();
907         if ( success == false )
908         {
909             cbMessageBox(_("Failed to clear events array."), _("Error"), wxICON_ERROR);
910         }
911 
912         // Restores label and enables all search params graphical widgets.
913         UpdateSearchButtons(true, search);
914         EnableControls(true);
915     }
916 
917     return success;
918 }
919 
IsSearchRunning()920 bool ThreadSearchView::IsSearchRunning()
921 {
922     bool searchRunning = (m_pFindThread != 0);
923 
924     if ( m_MutexSearchEventsArray.Lock() == wxMUTEX_NO_ERROR )
925     {
926         // If user clicked on Cancel or thread is finished, there may be remaining
927         // events to display in the array. In this case, we consider the search is
928         // stil running even if thread is over.
929         searchRunning = searchRunning || (m_ThreadSearchEventsArray.GetCount() > 0);
930         m_MutexSearchEventsArray.Unlock();
931     }
932 
933     return searchRunning;
934 }
935 
936 
UpdateSearchButtons(bool enable,eSearchButtonLabel label)937 void ThreadSearchView::UpdateSearchButtons(bool enable, eSearchButtonLabel label)
938 {
939     // Labels and pictures paths
940     wxString searchButtonLabels[] = {_("Search"), _("Cancel search"), wxEmptyString};
941 
942     wxString searchButtonPathsEnabled[]  = {wxT("findf.png"),
943                                             wxT("stop.png") ,
944                                             wxEmptyString};
945 
946     wxString searchButtonPathsDisabled[] = {wxT("findfdisabled.png"),
947                                             wxT("stopdisabled.png") ,
948                                             wxEmptyString};
949 
950     // Gets toolbar search button pointer
951     // Changes label/bitmap only if requested
952     if (label != skip)
953     {
954         {
955             const wxString &prefix = GetImagePrefix(false, m_pBtnSearch);
956             const double scaleFactor = cbGetContentScaleFactor(*m_pBtnSearch);
957             wxBitmap bmpSearch=cbLoadBitmapScaled(prefix + searchButtonPathsEnabled[label],
958                                                   wxBITMAP_TYPE_PNG, scaleFactor);
959             wxBitmap bmpSearchDisabled=cbLoadBitmapScaled(prefix + searchButtonPathsDisabled[label],
960                                                           wxBITMAP_TYPE_PNG, scaleFactor);
961 
962             m_pBtnSearch->SetToolTip(searchButtonLabels[label]);
963             m_pBtnSearch->SetBitmapLabel(bmpSearch);
964             m_pBtnSearch->SetBitmapDisabled(bmpSearchDisabled);
965         }
966 
967         {
968             //Toolbar buttons
969             const wxString &prefix = GetImagePrefix(true);
970             const double scaleFactor = cbGetContentScaleFactor(*m_pToolBar);
971             wxBitmap bmpSearch=cbLoadBitmapScaled(prefix + searchButtonPathsEnabled[label],
972                                                   wxBITMAP_TYPE_PNG, scaleFactor);
973             wxBitmap bmpSearchDisabled=cbLoadBitmapScaled(prefix + searchButtonPathsDisabled[label],
974                                                           wxBITMAP_TYPE_PNG, scaleFactor);
975             m_pToolBar->SetToolNormalBitmap(controlIDs.Get(ControlIDs::idBtnSearch), bmpSearch);
976             m_pToolBar->SetToolDisabledBitmap(controlIDs.Get(ControlIDs::idBtnSearch),
977                                               bmpSearchDisabled);
978         }
979     }
980 
981     // Sets enable state
982     m_pBtnSearch->Enable(enable);
983     m_pToolBar->EnableTool(controlIDs.Get(ControlIDs::idBtnSearch), enable);
984 }
985 
GetImagePrefix(bool toolbar,wxWindow * window)986 wxString GetImagePrefix(bool toolbar, wxWindow *window)
987 {
988     if (toolbar)
989     {
990         const int size = Manager::Get()->GetImageSize(Manager::UIComponent::Toolbars);
991         return ConfigManager::GetDataFolder()
992             + wxString::Format(wxT("/ThreadSearch.zip#zip:images/%dx%d/"), size, size);
993     }
994     else
995     {
996         cbAssert(window != nullptr);
997         const int targetHeight = floor(16 * cbGetActualContentScaleFactor(*window));
998         const int size = cbFindMinSize16to64(targetHeight);
999         return ConfigManager::GetDataFolder()
1000             + wxString::Format(wxT("/ThreadSearch.zip#zip:images/%dx%d/"), size, size);
1001     }
1002 }
1003 
ShowSearchControls(bool show)1004 void ThreadSearchView::ShowSearchControls(bool show)
1005 {
1006     bool     redraw    = false;
1007     wxSizer* pTopSizer = GetSizer();
1008 
1009     // ThreadSearchPlugin update
1010     m_ThreadSearchPlugin.SetShowSearchControls(show);
1011 
1012     // We show/hide search controls only if necessary
1013     if ( m_pBtnSearch->IsShown() != show )
1014     {
1015         pTopSizer->Show(m_pSizerSearchItems, show, true);
1016         redraw = true;
1017     }
1018 
1019     // When we show search controls, user might have hidden the
1020     // directory search controls to spare space.
1021     // In this case, we restore dir control show state
1022     if ( show == true )
1023     {
1024         show = m_ThreadSearchPlugin.GetShowDirControls();
1025     }
1026 
1027     if ( m_pPnlDirParams->IsShown() != show )
1028     {
1029         pTopSizer->Show(m_pSizerSearchDirItems, show, true);
1030         redraw = true;
1031     }
1032 
1033     if ( redraw == true )
1034     {
1035         pTopSizer->Layout();
1036     }
1037 }
1038 
1039 
ApplySplitterSettings(bool showCodePreview,long splitterMode)1040 void ThreadSearchView::ApplySplitterSettings(bool showCodePreview, long splitterMode)
1041 {
1042     if ( showCodePreview == true )
1043     {
1044         if ( (m_pSplitter->IsSplit() == false) || (splitterMode != m_pSplitter->GetSplitMode()) )
1045         {
1046             if ( m_pSplitter->IsSplit() == true ) m_pSplitter->Unsplit();
1047             if ( splitterMode == wxSPLIT_HORIZONTAL )
1048     {
1049                 m_pSplitter->SplitHorizontally(m_pPnlListLog, m_pPnlPreview);
1050             }
1051             else
1052         {
1053             m_pSplitter->SplitVertically(m_pPnlPreview, m_pPnlListLog);
1054         }
1055     }
1056     }
1057     else
1058     {
1059         if ( m_pSplitter->IsSplit() == true )
1060         {
1061             m_pSplitter->Unsplit(m_pPnlPreview);
1062         }
1063     }
1064 }
1065 
1066 
SetLoggerType(ThreadSearchLoggerBase::eLoggerTypes lgrType)1067 void ThreadSearchView::SetLoggerType(ThreadSearchLoggerBase::eLoggerTypes lgrType)
1068 {
1069     if ( lgrType != m_pLogger->GetLoggerType() )
1070     {
1071         delete m_pLogger;
1072         m_pLogger = ThreadSearchLoggerBase::BuildThreadSearchLoggerBase(*this
1073                                                                        , m_ThreadSearchPlugin
1074                                                                        , lgrType
1075                                                                        , m_ThreadSearchPlugin.GetFileSorting()
1076                                                                        , m_pPnlListLog
1077                                                                        , controlIDs.Get(ControlIDs::idWndLogger));
1078         m_pPnlListLog->GetSizer()->Add(m_pLogger->GetWindow(), 1, wxEXPAND|wxFIXED_MINSIZE, 0);
1079         wxSizer* pTopSizer = m_pPnlListLog->GetSizer();
1080         pTopSizer->Layout();
1081     }
1082 }
1083 
1084 
SetSashPosition(int position,const bool redraw)1085 void ThreadSearchView::SetSashPosition(int position, const bool redraw)
1086 {
1087     m_pSplitter->SetSashPosition(position, redraw);
1088 }
1089 
1090 
GetSashPosition() const1091 int ThreadSearchView::GetSashPosition() const
1092 {
1093     return m_pSplitter->GetSashPosition();
1094 }
1095 
1096 
SetSearchHistory(const wxArrayString & searchPatterns,const wxArrayString & searchDirs,const wxArrayString & searchMasks)1097 void ThreadSearchView::SetSearchHistory(const wxArrayString& searchPatterns, const wxArrayString& searchDirs,
1098                                         const wxArrayString& searchMasks)
1099 {
1100     m_pCboSearchExpr->Append(searchPatterns);
1101     if ( searchPatterns.GetCount() > 0 )
1102     {
1103         m_pCboSearchExpr->SetSelection(0);
1104     }
1105     m_pPnlDirParams->SetSearchHistory(searchDirs, searchMasks);
1106 }
1107 
1108 
GetSearchHistory() const1109 wxArrayString ThreadSearchView::GetSearchHistory() const
1110 {
1111     return m_pCboSearchExpr->GetStrings();
1112 }
1113 
GetSearchDirsHistory() const1114 wxArrayString ThreadSearchView::GetSearchDirsHistory() const
1115 {
1116     return m_pPnlDirParams->GetSearchDirsHistory();
1117 }
1118 
GetSearchMasksHistory() const1119 wxArrayString ThreadSearchView::GetSearchMasksHistory() const
1120 {
1121     return m_pPnlDirParams->GetSearchMasksHistory();
1122 }
1123 
1124 // BEGIN Duplicated from cbeditor.cpp to apply folding options
SetMarkerStyle(int marker,int markerType,wxColor fore,wxColor back)1125 void ThreadSearchView::SetMarkerStyle(int marker, int markerType, wxColor fore, wxColor back)
1126 {
1127     m_pSearchPreview->MarkerDefine(marker, markerType);
1128     m_pSearchPreview->MarkerSetForeground(marker, fore);
1129     m_pSearchPreview->MarkerSetBackground(marker, back);
1130 }
1131 
1132 
UnderlineFoldedLines(bool underline)1133 void ThreadSearchView::UnderlineFoldedLines(bool underline)
1134 {
1135     m_pSearchPreview->SetFoldFlags(underline? 16 : 0);
1136 }
1137 
1138 
SetFoldingIndicator(int id)1139 void ThreadSearchView::SetFoldingIndicator(int id)
1140 {
1141     //Arrow
1142     if(id == 0)
1143     {
1144         SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_ARROWDOWN, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1145         SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_ARROW, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1146         SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1147         SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1148         SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_ARROW, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1149         SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_ARROWDOWN, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1150         SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1151     }
1152 
1153     //Circle
1154     else if(id == 1)
1155     {
1156         SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_CIRCLEMINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1157         SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_CIRCLEPLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1158         SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_VLINE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1159         SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_LCORNERCURVE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1160         SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_CIRCLEPLUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1161         SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_CIRCLEMINUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1162         SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_TCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1163     }
1164 
1165     //Square
1166     else if(id == 2)
1167     {
1168         SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_BOXMINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1169         SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_BOXPLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1170         SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_VLINE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1171         SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_LCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1172         SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_BOXPLUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1173         SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_BOXMINUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1174         SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_TCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1175     }
1176 
1177     //Simple
1178     else if(id == 3)
1179     {
1180         SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_MINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1181         SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_PLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1182         SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1183         SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1184         SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_PLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1185         SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_MINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1186         SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1187     }
1188 }
1189 // END Duplicated from cbeditor.cpp to apply folding options
1190