NCBI C++ ToolKit
track_list_ctrl.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: track_list_ctrl.cpp 43790 2019-08-30 16:32:37Z katargir $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Roman Katargin
27  *
28  * File Description:
29  *
30  */
31 #include <ncbi_pch.hpp>
32 
33 #include <wx/imaglist.h>
34 
35 #include "track_list_ctrl.hpp"
36 
38 
39 #include <wx/dcmemory.h>
40 
42 
43 wxDEFINE_EVENT(wxEVT_SET_VISIBILITY, wxCommandEvent);
44 
45 #define EVT_SET_VISIBILITY(id, fn) \
46  DECLARE_EVENT_TABLE_ENTRY( \
47  wxEVT_SET_VISIBILITY, id, wxID_ANY, \
48  wxCommandEventHandler(fn), \
49  (wxObject *) NULL \
50  ),
51 
52 BEGIN_EVENT_TABLE(CTrackListCtrl, wxListCtrl)
53  EVT_LEFT_DOWN(CTrackListCtrl::OnLeftDown)
54  EVT_LIST_COL_CLICK(wxID_ANY, CTrackListCtrl::OnColumnClick)
57 
58 static wxBitmap s_BitmapFrom7x4(int w, int h, const char* const * bits)
59 {
60  vector<string> strings;
61 
62  if (w <= 0 || h <= 0)
63  return wxBitmap(w, h);
64 
65  strings.push_back(NStr::NumericToString(w) + " " + NStr::NumericToString(h) + " 2 1");
66  strings.emplace_back(" c None");
67  strings.emplace_back("X c Gray25");
68 
69  for (int i = 0; i < h; ++i) {
70  strings.emplace_back(w, ' ');
71  int ii = i - (h - 4) / 2;
72  if (ii >= 0 && ii < 4) {
73  if (w < 7)
74  strings.back().replace(0, w, string(bits[ii] + (7 - w) / 2, w));
75  else
76  strings.back().replace((w - 7) / 2, 7, string(bits[ii], 7));
77  }
78  }
79 
80  vector<const char*> xpm;
81  for (const string& s : strings)
82  xpm.push_back(s.c_str());
83 
84  return wxBitmap(&xpm[0]);
85 }
86 
87 CTrackListCtrl::CTrackListCtrl(wxWindow *parent, wxWindowID id, const wxPoint&, const wxSize&, long, const wxValidator&, const wxString&)
88  : m_ImageList(), m_SortColumn(0)
89 {
90  wxListCtrl::Create(parent, id, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_VIRTUAL);
91 
93  wxSize size = m_ImageList->GetSize();
94 
95  static const char * up_xpm[] = {
96  " X ",
97  " XXX ",
98  " XXXXX ",
99  "XXXXXXX"};
100 
101  static const char * dn_xpm[] = {
102  "XXXXXXX",
103  " XXXXX ",
104  " XXX ",
105  " X "};
106 
108  m_ImageList->Add(s_BitmapFrom7x4(size.x, size.y, dn_xpm));
109 
110  SetImageList(m_ImageList, wxIMAGE_LIST_SMALL);
111 
112  InsertColumn(0, wxT("Track Name"), wxLIST_FORMAT_LEFT, 250);
113  InsertColumn(1, wxT("Accession"), wxLIST_FORMAT_LEFT);
114  InsertColumn(2, wxT("Category"), wxLIST_FORMAT_LEFT);
115  InsertColumn(3, wxT("Description"), wxLIST_FORMAT_LEFT);
116 
117  x_UpdateHeader();
118  x_Sort();
119 }
120 
122 {
123  delete m_ImageList;
124 }
125 
127 {
128  m_Tracks = tracks;
130 
131  SetItemCount(m_TracksVisible.size());
132  SetColumnWidth(1, wxLIST_AUTOSIZE);
133  x_Sort();
134  Refresh();
135 }
136 
137 void CTrackListCtrl::OnLeftDown(wxMouseEvent& evt)
138 {
139  int flags;
140  long item = HitTest(evt.GetPosition(), flags);
141  if (item >= 0 && item < (long)m_TracksVisible.size() && (flags & wxLIST_HITTEST_ONITEMICON)) {
142  ITrackInfo* track = m_TracksVisible[item];
143  wxCommandEvent eventCustom(wxEVT_SET_VISIBILITY);
144  eventCustom.SetInt(track->GetVisible() ? 0 : 1);
145  wxPostEvent(this, eventCustom);
146  if (!GetItemState(item, wxLIST_STATE_SELECTED))
147  evt.Skip();
148  }
149  else {
150  evt.Skip();
151  }
152 }
153 
154 void CTrackListCtrl::OnColumnClick(wxListEvent &evt)
155 {
156  int col = evt.GetColumn();
157  if (col < 0)
158  m_SortColumn = 0;
159  else {
160  if (abs(m_SortColumn) == col + 1) {
162  reverse(m_TracksVisible.begin(), m_TracksVisible.end());
163  }
164  else {
165  m_SortColumn = col + 1;
166  x_Sort();
167  }
168  }
169  x_UpdateHeader();
170  Refresh();
171 }
172 
174 {
175  for (int i = 0; i < GetColumnCount(); ++i) {
176  wxListItem item;
177  item.SetAlign(wxLIST_FORMAT_LEFT);
178  if (abs(m_SortColumn) == i + 1)
179  item.SetImage(m_SortColumn < 0 ? 5 : 4);
180  else
181  item.SetImage(-1);
182  item.SetMask(wxLIST_MASK_IMAGE | wxLIST_MASK_FORMAT);
183  SetColumn(i, item);
184  }
185 }
186 
188 {
189  wxBusyCursor wait;
190 
191  if (m_TracksVisible.size() < 2)
192  return;
193 
194  if (abs(m_SortColumn) == 1)
195  sort(m_TracksVisible.begin(), m_TracksVisible.end(),
196  [](const ITrackInfo* t1, const ITrackInfo* t2)
197  -> bool { return NStr::CompareNocase(t1->GetDisplayName(), t2->GetDisplayName()) < 0; });
198  else if (abs(m_SortColumn) == 2)
199  sort(m_TracksVisible.begin(), m_TracksVisible.end(),
200  [](const ITrackInfo* t1, const ITrackInfo* t2)
201  -> bool { string s1 = t1->GetAccession(); if (!NStr::StartsWith(s1, "NA")) s1 = NcbiEmptyString;
202  string s2 = t2->GetAccession(); if (!NStr::StartsWith(s2, "NA")) s2 = NcbiEmptyString;
203  return NStr::CompareNocase(s1, s2) < 0; });
204  else if (abs(m_SortColumn) == 3)
205  sort(m_TracksVisible.begin(), m_TracksVisible.end(),
206  [](const ITrackInfo* t1, const ITrackInfo* t2)
207  -> bool { return NStr::CompareNocase(t1->GetCategory(), t2->GetCategory()) < 0; });
208  else if (abs(m_SortColumn) == 4)
209  sort(m_TracksVisible.begin(), m_TracksVisible.end(),
210  [](const ITrackInfo* t1, const ITrackInfo* t2)
211  -> bool { return NStr::CompareNocase(t1->GetComments(), t2->GetComments()) < 0; });
212  else
213  return;
214 
215  if (m_SortColumn < 0)
216  reverse(m_TracksVisible.begin(), m_TracksVisible.end());
217 }
218 
219 void CTrackListCtrl::OnSetVisibility(wxCommandEvent& evt)
220 {
221  bool visible = evt.IsChecked();
222 
223  for (long item = -1;;) {
224  item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
225  if (item == -1) break;
226  ITrackInfo* track = m_TracksVisible[item];
227  track->SetVisible(visible);
228  RefreshItem(item);
229  }
230 }
231 
232 wxString CTrackListCtrl::OnGetItemText(long item, long column) const
233 {
234  if (item < 0 || item >= (long)m_TracksVisible.size())
235  return wxEmptyString;
236 
237  ITrackInfo* track = m_TracksVisible[item];
238 
239  if (column == 0) {
240  string trackName = track->GetDisplayName();
241  return wxString::FromUTF8(trackName.c_str());
242  }
243 
244  if (column == 1) {
245  string accession = track->GetAccession();
246  if (NStr::StartsWith(accession, "NA"))
247  return wxString::FromUTF8(accession.c_str());
248  else
249  return wxEmptyString;
250  }
251 
252  if (column == 2) {
253  string category = track->GetCategory();
254  return wxString::FromUTF8(category.c_str());
255  }
256 
257  if (column == 3) {
258  string description = track->GetComments();
259  return wxString::FromUTF8(description.c_str());
260  }
261 
262  return wxEmptyString;
263 }
264 
265 int CTrackListCtrl::OnGetItemImage(long item) const
266 {
267  if (item < 0 || item >= (long)m_TracksVisible.size())
268  return 0;
269 
270  ITrackInfo* track = m_TracksVisible[item];
271  return track->GetVisible() ? 1 : 0;
272 }
273 
274 void CTrackListCtrl::FilterValues(const string& filter)
275 {
276  if (filter.empty()) {
278  }
279  else {
280  m_TracksVisible.clear();
281  for (auto i : m_Tracks) {
282  string trackName = i->GetDisplayName();
283  string accession = i->GetAccession();
284  if (NStr::FindNoCase(trackName, filter) == NPOS &&
285  NStr::FindNoCase(accession, filter) == NPOS)
286  continue;
287  m_TracksVisible.push_back(i);
288  }
289  }
290  x_Sort();
291  SetItemCount(m_TracksVisible.size());
292  Refresh();
293 }
294 
295 static const char* kWidths = "Widths";
296 
298 {
299  vector<int> widths;
300  view.GetIntVec(kWidths, widths);
301 
302  if ((int)widths.size() == GetColumnCount()) {
303  for (int i = 0; i < GetColumnCount(); ++i) {
304  int w = widths[i];
305  if (w > 0) SetColumnWidth(i, w);
306  }
307  }
308 }
309 
311 {
312  vector<int> widths;
313  for (int i = 0; i < GetColumnCount(); ++i)
314  widths.push_back(GetColumnWidth(i));
315 
316  if (widths.size() > 0)
317  view.Set(kWidths, widths);
318 }
319 
#define static
class CRegistryReadView provides a nested hierarchical view at a particular key.
Definition: reg_view.hpp:58
void GetIntVec(const string &key, vector< int > &val) const
Definition: reg_view.cpp:252
void Set(const string &key, int val)
access a named key at this level, with no recursion
Definition: reg_view.cpp:533
virtual void SetVisible(bool visible)=0
virtual bool GetVisible() const =0
virtual string GetComments() const =0
virtual string GetAccession() const =0
virtual string GetDisplayName() const =0
virtual string GetCategory() const =0
vector< ITrackInfo * > TTracks
void FilterValues(const string &filter)
wxImageList * m_ImageList
void OnColumnClick(wxListEvent &evt)
void LoadSettings(const CRegistryReadView &view)
void OnSetVisibility(wxCommandEvent &evt)
void SetTracks(const TTracks &tracks)
void SaveSettings(CRegistryWriteView view) const
virtual wxString OnGetItemText(long item, long column) const
CTrackListCtrl(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxLC_REPORT|wxLC_VIRTUAL|wxLC_SINGLE_SEL, const wxValidator &validator=wxDefaultValidator, const wxString &name=wxListCtrlNameStr)
void OnLeftDown(wxMouseEvent &evt)
virtual int OnGetItemImage(long item) const
static uch flags
static const char * up_xpm[]
static const char * column
Definition: stats.c:23
static const char *const strings[]
Definition: utf8.c:21
string
Definition: cgiapp.hpp:690
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern, SIZE_TYPE start, SIZE_TYPE end, EOccurrence which=eFirst)
Find the pattern in the specified range of a string using a case insensitive search.
Definition: ncbistr.cpp:2984
#define NPOS
Definition: ncbistr.hpp:133
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5406
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
END_EVENT_TABLE()
int i
#define wxT(x)
Definition: muParser.cpp:41
constexpr auto sort(_Init &&init)
const struct ncbi::grid::netcache::search::fields::SIZE size
#define abs(a)
Definition: ncbi_heapmgr.c:130
static static static wxID_ANY
static wxBitmap s_BitmapFrom7x4(int w, int h, const char *const *bits)
static const char * kWidths
#define EVT_SET_VISIBILITY(id, fn)
wxDEFINE_EVENT(wxEVT_SET_VISIBILITY, wxCommandEvent)
wxImageList * CreateCheckboxImages(wxWindow *wnd)
Definition: wx_utils.cpp:1352
#define const
Definition: zconf.h:232
Modified on Fri Sep 20 14:57:57 2024 by modify_doxy.py rev. 669887