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

Go to the SVN repository for this file.

1 /* $Id: wx_phylo_edit_dlg.cpp 47479 2023-05-02 13:24:02Z ucko $
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: Vladimir Tereshkov
27  *
28  * File Description:
29  *
30  */
31 
32 
33 #include <ncbi_pch.hpp>////@begin includes
34 ////@end includes
35 
36 
41 
44 
46 #include <gui/utils/rgba_color.hpp>
47 
49 
50 #include <wx/panel.h>
51 #include <wx/stattext.h>
52 #include <wx/statline.h>
53 #include <wx/statbox.h>
54 #include <wx/combobox.h>
55 #include <wx/sizer.h>
56 #include <wx/clrpicker.h>
57 #include <wx/checklst.h>
58 #include <wx/valgen.h>
59 #include <wx/bitmap.h>
60 #include <wx/icon.h>
61 #include <wx/listbook.h>
62 #include <wx/listctrl.h>
63 #include <wx/msgdlg.h>
64 
65 ////@begin XPM images
66 ////@end XPM images
67 
69 
70 IMPLEMENT_DYNAMIC_CLASS( CwxPhyloEditDlg, wxDialog )
71 
72 BEGIN_EVENT_TABLE( CwxPhyloEditDlg, wxDialog )
73 
74 ////@begin CwxPhyloEditDlg event table entries
75  EVT_LIST_ITEM_SELECTED( ID_LISTCTRL1, CwxPhyloEditDlg::OnListctrl1Selected )
76  EVT_LIST_ITEM_DESELECTED( ID_LISTCTRL1, CwxPhyloEditDlg::OnListctrl1Deselected )
77 
79 
81 
83 
85 
86  EVT_BUTTON( wxID_OK, CwxPhyloEditDlg::OnOkClick )
87 
88 ////@end CwxPhyloEditDlg event table entries
89 
91 
93 : m_Tree(NULL)
94 , m_NodeIdx(CPhyloTree::Null())
95 , m_UpdatedFeature(NULL)
96 {
97  Init();
98 }
99 
100 CwxPhyloEditDlg::CwxPhyloEditDlg( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
101 : m_Tree(NULL)
102 , m_NodeIdx(CPhyloTree::Null())
103 , m_UpdatedFeature(NULL)
104 {
105  Init();
106  Create(parent, id, caption, pos, size, style);
107 }
108 
109 bool CwxPhyloEditDlg::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
110 {
111 ////@begin CwxPhyloEditDlg creation
112  SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY|wxWS_EX_BLOCK_EVENTS);
113  wxDialog::Create( parent, id, caption, pos, size, style );
114 
115  CreateControls();
116  if (GetSizer())
117  {
118  GetSizer()->SetSizeHints(this);
119  }
120  Centre();
121 ////@end CwxPhyloEditDlg creation
122  return true;
123 }
124 
126 {
127 ////@begin CwxPhyloEditDlg destruction
128 ////@end CwxPhyloEditDlg destruction
129 }
130 
132 {
133 ////@begin CwxPhyloEditDlg member initialisation
134  m_List = NULL;
135  m_Name = NULL;
136  m_Value = NULL;
138 ////@end CwxPhyloEditDlg member initialisation
139 }
140 
142 {
143 ////@begin CwxPhyloEditDlg content construction
144  CwxPhyloEditDlg* itemDialog1 = this;
145 
146  wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
147  itemDialog1->SetSizer(itemBoxSizer2);
148 
149  wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
150  itemBoxSizer2->Add(itemBoxSizer3, 0, wxGROW|wxALL, 5);
151 
152  m_List = new wxListCtrl( itemDialog1, ID_LISTCTRL1, wxDefaultPosition, wxSize(300, 120), wxLC_REPORT );
153  itemBoxSizer3->Add(m_List, 0, wxALIGN_TOP|wxALL, 5);
154 
155  wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxVERTICAL);
156  itemBoxSizer3->Add(itemBoxSizer5, 0, wxALIGN_TOP|wxALL, 5);
157 
158  wxButton* itemButton6 = new wxButton( itemDialog1, ID_BUTTON4, _("Add"), wxDefaultPosition, wxDefaultSize, 0 );
159  itemBoxSizer5->Add(itemButton6, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
160 
161  wxButton* itemButton7 = new wxButton( itemDialog1, ID_BUTTON5, _("Remove"), wxDefaultPosition, wxDefaultSize, 0 );
162  itemBoxSizer5->Add(itemButton7, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
163 
164  wxButton* itemButton8 = new wxButton( itemDialog1, ID_BUTTON, _("Update"), wxDefaultPosition, wxDefaultSize, 0 );
165  itemBoxSizer5->Add(itemButton8, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
166 
167  wxStaticBox* itemStaticBoxSizer9Static = new wxStaticBox(itemDialog1, wxID_ANY, wxEmptyString);
168  wxStaticBoxSizer* itemStaticBoxSizer9 = new wxStaticBoxSizer(itemStaticBoxSizer9Static, wxVERTICAL);
169  itemBoxSizer2->Add(itemStaticBoxSizer9, 1, wxGROW|wxALL, 5);
170 
171  wxBoxSizer* itemBoxSizer10 = new wxBoxSizer(wxHORIZONTAL);
172  itemStaticBoxSizer9->Add(itemBoxSizer10, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT, 5);
173 
174  wxStaticText* itemStaticText11 = new wxStaticText( itemDialog1, wxID_STATIC, _("Name"), wxDefaultPosition, wxDefaultSize, 0 );
175  itemBoxSizer10->Add(itemStaticText11, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
176 
177  m_Name = new wxTextCtrl( itemDialog1, ID_TEXTCTRL14, wxEmptyString, wxDefaultPosition, wxSize(150, -1), 0 );
178  itemBoxSizer10->Add(m_Name, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
179 
180  wxBoxSizer* itemBoxSizer13 = new wxBoxSizer(wxHORIZONTAL);
181  itemStaticBoxSizer9->Add(itemBoxSizer13, 1, wxGROW|wxLEFT|wxRIGHT, 5);
182 
183  wxBoxSizer* itemBoxSizer14 = new wxBoxSizer(wxHORIZONTAL);
184  itemBoxSizer13->Add(itemBoxSizer14, 1, wxALIGN_TOP|wxRIGHT|wxTOP|wxBOTTOM, 5);
185 
186  wxStaticText* itemStaticText15 = new wxStaticText( itemDialog1, wxID_STATIC, _("Value"), wxDefaultPosition, wxDefaultSize, 0 );
187  itemBoxSizer14->Add(itemStaticText15, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
188 
189  m_Value = new wxTextCtrl( itemDialog1, ID_TEXTCTRL15, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
190  itemBoxSizer14->Add(m_Value, 1, wxGROW|wxALL, 5);
191 
192  wxStaticText* itemStaticText17 = new wxStaticText( itemDialog1, wxID_STATIC, _("Color"), wxDefaultPosition, wxDefaultSize, 0 );
193  itemBoxSizer14->Add(itemStaticText17, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
194 
195  m_ColorPicker = new wxColourPickerCtrl( itemDialog1, ID_COLOURCTRL, wxColour(0, 255, 0), wxDefaultPosition, wxDefaultSize, wxCLRP_DEFAULT_STYLE );
196  itemBoxSizer13->Add(m_ColorPicker, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
197 
198  wxStaticLine* itemStaticLine19 = new wxStaticLine( itemDialog1, ID_STATICLINE1, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
199  itemBoxSizer2->Add(itemStaticLine19, 0, wxGROW|wxALL, 5);
200 
201  wxStdDialogButtonSizer* itemStdDialogButtonSizer20 = new wxStdDialogButtonSizer;
202 
203  itemBoxSizer2->Add(itemStdDialogButtonSizer20, 0, wxALIGN_RIGHT|wxALL, 5);
204  wxButton* itemButton21 = new wxButton( itemDialog1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
205  itemStdDialogButtonSizer20->AddButton(itemButton21);
206 
207  wxButton* itemButton22 = new wxButton( itemDialog1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
208  itemStdDialogButtonSizer20->AddButton(itemButton22);
209 
210  itemStdDialogButtonSizer20->Realize();
211 
212 ////@end CwxPhyloEditDlg content construction
213 }
214 
215 void CwxPhyloEditDlg::OnButton4Click( wxCommandEvent& event )
216 {
217  // validate data: not blank, does not duplicate other items
218  wxString n = m_Name->GetValue();
219  n.Trim(true);
220  n.Trim(false);
221  if (n.Length() == 0)
222  return;
223 
224  std::string n_lower = ToStdString(n);
225  NStr::ToLower(n_lower);
226 
227  // iterate through listctrl so that we don't add duplicates
228  long item_num = -1;
229  for ( ;; ) {
230  item_num = m_List->GetNextItem(item_num,
231  wxLIST_NEXT_ALL,
232  wxLIST_STATE_DONTCARE);
233  if ( item_num == -1 )
234  break;
235 
236  wxListItem info;
237  info.m_itemId = item_num;
238  info.m_mask = wxLIST_MASK_TEXT;
239  info.m_col = 0;
240  string name = m_List->GetItem(info) ? ToStdString(info.m_text) : string();
241 
242  if (NStr::ToLower(name) == NStr::ToLower(n_lower)) {
243  wxString msg = wxT("Item '");
244  msg += n;
245  msg += wxT("' is already a property.\n");
246  msg += wxT("Select the property from the list to update it.");
247 
248  wxMessageBox(msg, wxT("Duplicate Property Name"),
249  wxOK | wxICON_WARNING);
250 
251  return;
252  }
253  }
254 
255  // add property:
256  wxListItem * item = new wxListItem();
257  auto itemId = m_List->InsertItem(*item);
258  m_List->SetItem(itemId, 0, m_Name->GetValue());
259  m_List->SetItem(itemId, 1, m_Value->GetValue());
260  event.Skip();
261 }
262 
263 void CwxPhyloEditDlg::OnButton5Click( wxCommandEvent& event )
264 {
265  // delete button
266  if (m_List->GetSelectedItemCount() == 0)
267  return;
268 
269  // find selected item index
270  auto index = m_List->GetNextItem(-1,
271  wxLIST_NEXT_ALL,
272  wxLIST_STATE_SELECTED);
273 
274  m_List->DeleteItem(index);
275 
276  event.Skip();
277 }
278 
279 void CwxPhyloEditDlg::OnButtonClick( wxCommandEvent& event )
280 {
281  // update
283  event.Skip();
284 }
285 
286 void CwxPhyloEditDlg::OnOkClick( wxCommandEvent& event )
287 {
288  // iterate through listctrl
289  long item = -1;
290  for ( ;; ) {
291  item = m_List->GetNextItem(item,
292  wxLIST_NEXT_ALL,
293  wxLIST_STATE_DONTCARE);
294  if ( item == -1 )
295  break;
296 
297  wxListItem info;
298  info.m_itemId = item;
299  info.m_mask = wxLIST_MASK_TEXT;
300  info.m_col = 0;
301  string name = m_List->GetItem(info) ? ToStdString(info.m_text) : string();
302  info.m_col = 1;
303  string value = m_List->GetItem(info) ? ToStdString(info.m_text) : string();
304 
306 
308  id = m_UpdatedFeature->GetDictionary().GetId(name);
309  }
310  else { // find smallest available id
311  for (id=0; id < 255; id++){
314  break;
315  }
316  }
317  // should probably put the 255 in bio_tree if we are serious about it
318  if (id==255) {
320  "CPhyloTreeNode::SetFeature - maximum number of features exceeded");
321  }
322  }
323  m_UpdatedFeature->GetUpdated()[0].GetFeatures().SetFeature(id, value);
324  }
325 
326  event.Skip();
327 }
328 
330 {
331  return true;
332 }
333 wxBitmap CwxPhyloEditDlg::GetBitmapResource( const wxString& name )
334 {
335  // Bitmap retrieval
336 ////@begin CwxPhyloEditDlg bitmap retrieval
337  wxUnusedVar(name);
338  return wxNullBitmap;
339 ////@end CwxPhyloEditDlg bitmap retrieval
340 }
341 wxIcon CwxPhyloEditDlg::GetIconResource( const wxString& name )
342 {
343  // Icon retrieval
344 ////@begin CwxPhyloEditDlg icon retrieval
345  wxUnusedVar(name);
346  return wxNullIcon;
347 ////@end CwxPhyloEditDlg icon retrieval
348 }
349 
351  CPhyloTree::TTreeIdx node_idx,
352  CFeatureEdit* updated_feature)
353 {
354  m_Tree = tree;
355  m_NodeIdx = node_idx;
356  m_UpdatedFeature = updated_feature;
357 
358  int w = m_List->GetSize().GetWidth();
359 
360  // make value 2/3 of list width, and name 1/3.
361  m_List->InsertColumn(0, wxT("Name"), wxLIST_FORMAT_LEFT, w/3 );
362  m_List->InsertColumn(1, wxT("Value"), wxLIST_FORMAT_LEFT, (w*2)/3 );
363 
365  const CBioTreeFeatureList & flist = (*m_Tree)[m_NodeIdx]->GetBioTreeFeatureList();
366 
368  if (dict.HasFeature(it->id)){
369  string sName = dict.GetFeatureDict().find(it->id)->second;
370  string sValue = it->value;
371 
372  wxListItem * item = new wxListItem();
373  auto itemId = m_List->InsertItem(*item);
374 
375  m_List->SetItem(itemId, 0, ToWxString(sName));
376  m_List->SetItem(itemId, 1, ToWxString(sValue));
377  }
378  }
379 }
380 
381 
382 void CwxPhyloEditDlg::OnListctrl1Selected( wxListEvent& event )
383 {
384  if (m_List->GetSelectedItemCount() == 0)
385  return;
386 
387  // find selected item index
388  auto index = m_List->GetNextItem(-1,
389  wxLIST_NEXT_ALL,
390  wxLIST_STATE_SELECTED);
391 
392  wxListItem info;
393  info.m_itemId = index;
394  info.m_mask = wxLIST_MASK_TEXT;
395  info.m_col = 0;
396  wxString name = m_List->GetItem(info) ? info.m_text : wxT("");
397  info.m_col = 1;
398  wxString value = m_List->GetItem(info) ? info.m_text : wxT("");
399 
400 
401  // If there is already a color string in the properties put that color
402  // on the color picker control
403  string current_value = ToStdString(value);
404 
405  string::size_type idx1 = current_value.find_first_of('[');
406  if (idx1 != string::npos) {
407  string::size_type idx2 = current_value.find_first_of(']');
408  if (idx2 != string::npos && idx2 > idx1) {
409  // We have found a color (maybe - could also be other text between [ and ]...)
410  try {
411  string color_str = current_value.substr(idx1, idx2-idx1 + 1);
412  CRgbaColor color(color_str);
413 
414  /// Set color in color picker
415  m_ColorPicker->SetColour(wxColour(color.GetRedUC(),
416  color.GetGreenUC(),
417  color.GetBlueUC()));
418  }
419  catch (CException&) {
420  // Not a color - probably other string text (don't worry about it)
421  }
422  }
423  }
424 
425  m_Name->SetValue(name);
426  m_Value->SetValue(value);
427 
428  event.Skip();
429 }
430 
431 void CwxPhyloEditDlg::OnListctrl1Deselected( wxListEvent& event )
432 {
434  event.Skip();
435 }
436 
438 {
439  if (m_List->GetSelectedItemCount() == 0)
440  return;
441 
442  // find selected item index
443  auto index = m_List->GetNextItem(-1,
444  wxLIST_NEXT_ALL,
445  wxLIST_STATE_SELECTED);
446 
447  // Can't set the name to be blank:
448  wxString n = m_Name->GetValue();
449  n.Trim(true);
450  n.Trim(false);
451  if (n.Length() == 0)
452  return;
453 
454  m_List->SetItem(index, 0, m_Name->GetValue());
455  m_List->SetItem(index, 1, m_Value->GetValue());
456 
457 }
458 
459 void CwxPhyloEditDlg::OnColourctrlColourPickerChanged( wxColourPickerEvent& event )
460 {
461  // Convert wxColor to string format [r,g,b] where r,g,b are 0..255.
462  CRgbaColor new_color(ToStdString(event.GetColour().GetAsString(wxC2S_HTML_SYNTAX)));
463 
464  // If there is already a color string in the properties replace it. Otherwise
465  // insert the color value at the beginning of the text.
466  string current_value = ToStdString(m_Value->GetValue());
467 
468  string::size_type idx1 = current_value.find_first_of('[');
469  if (idx1 != string::npos) {
470  string::size_type idx2 = current_value.find_first_of(']');
471  if (idx2 != string::npos && idx2 > idx1) {
472  // We have found a color. Replace it.
473  string old_color_str = current_value.substr(idx1, idx2-idx1 + 1);
474 
475  try {
476  CRgbaColor old_color(old_color_str);
477 
478  // Retain the current alpha value since color picker does not let you
479  // choose that.
480  new_color.SetAlpha(old_color.GetAlpha());
481  string new_color_str = std::string("[") + new_color.ToString(true,true) + std::string("]");
482 
483  current_value.replace(idx1, idx2-idx1 + 1, new_color_str);
484  m_Value->SetValue(ToWxString(current_value));
485  return;
486  }
487  catch (CException&) {
488  // Not a color - probably other string text (don't worry about it)
489  }
490  }
491  }
492 
493  // Alpha of 255 is unreasonable (since you can't see nodes) so set default to 25%:
494  new_color.SetAlpha((unsigned char)64);
495  string new_color_str = std::string("[") + new_color.ToString(true,true) + std::string("]");
496  m_Value->SetValue(ToWxString(new_color_str + " " + current_value));
497 
498  event.Skip();
499 }
500 
502 
503 
504 
Things for representing and manipulating bio trees.
#define ID_TEXTCTRL14
Feature dictionary.
Definition: bio_tree.hpp:176
Features storage for the bio tree node.
Definition: bio_tree.hpp:101
Tree subclass also has functions and data needed for rendering and selection.
Definition: phylo_tree.hpp:52
CBioTreeFeatureDictionary & GetFeatureDict()
Return feature dictionary.
Definition: phylo_tree.hpp:323
class CRgbaColor provides a simple abstraction for managing colors.
Definition: rgba_color.hpp:58
void OnButton4Click(wxCommandEvent &event)
void SetParams(CPhyloTree *tree, CPhyloTree::TTreeIdx node_idx, CFeatureEdit *updated_feature)
void OnButtonClick(wxCommandEvent &event)
static bool ShowToolTips()
wxIcon GetIconResource(const wxString &name)
void OnColourctrlColourPickerChanged(wxColourPickerEvent &event)
void OnButton5Click(wxCommandEvent &event)
void OnListctrl1Selected(wxListEvent &event)
bool Create(wxWindow *parent, wxWindowID id=10000, const wxString &caption=_("Node Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(400, 300), long style=wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL)
wxBitmap GetBitmapResource(const wxString &name)
wxColourPickerCtrl * m_ColorPicker
CFeatureEdit * m_UpdatedFeature
CPhyloTree::TTreeIdx m_NodeIdx
void OnOkClick(wxCommandEvent &event)
void OnListctrl1Deselected(wxListEvent &event)
const_iterator find(const key_type &key) const
Definition: map.hpp:153
char value[7]
Definition: config.c:431
#define _(proto)
Definition: ct_nlmzip_i.h:78
static void Init(void)
Definition: cursor6.c:76
#define ID_BUTTON4
#define ID_BUTTON5
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define ID_LISTCTRL1
Definition: diag_panel.hpp:69
string ToString(bool printAlpha=true, bool uchars=true) const
Return a string representation of the current color.
Definition: rgba_color.cpp:309
void SetAlpha(float r)
Definition: rgba_color.cpp:287
float GetAlpha(void) const
Definition: rgba_color.hpp:339
#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 string & ToLower(string &str)
Convert string to lower case – string& version.
Definition: ncbistr.cpp:405
unsigned int TBioTreeFeatureId
Feature Id.
Definition: bio_tree.hpp:60
TBioTreeFeatureId GetId(const string &feature_name) const
If feature is already registered returns its id by name.
Definition: bio_tree.cpp:209
const TFeatureList & GetFeatureList() const
Return reference on the internal container.
Definition: bio_tree.hpp:130
TBioTreeFeatureId Register(const string &feature_name)
Register new feature, return its id.
Definition: bio_tree.cpp:160
bool HasFeature(const string &feature_name) const
Check if feature is listed in the dictionary.
Definition: bio_tree.cpp:146
const TFeatureDict & GetFeatureDict() const
Get reference on the internal map.
Definition: bio_tree.hpp:219
vector< CBioTreeFeaturePair > TFeatureList
Definition: bio_tree.hpp:103
n background color
END_EVENT_TABLE()
yy_size_t n
static MDB_envinfo info
Definition: mdb_load.c:37
#define wxT(x)
Definition: muParser.cpp:41
const struct ncbi::grid::netcache::search::fields::SIZE size
static static static wxID_ANY
Edits for one or more nodes.
vector< CUpdatedFeature > & GetUpdated()
CBioTreeFeatureDictionary & GetDictionary()
#define ID_STATICLINE1
#define ID_COLOURCTRL
#define ID_BUTTON
#define ID_TEXTCTRL15
wxString ToWxString(const string &s)
Definition: wx_utils.hpp:173
string ToStdString(const wxString &s)
Definition: wx_utils.hpp:161
Modified on Sat Dec 02 09:22:34 2023 by modify_doxy.py rev. 669887