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

Go to the SVN repository for this file.

1 /* $Id: selection_service.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: Andrey Yazhuk
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
36 
41 #include <gui/core/commands.hpp>
42 
46 
49 
50 #include <serial/iterator.hpp>
51 
52 #include <wx/panel.h>
53 #include <wx/sizer.h>
54 #include <wx/stattext.h>
55 
56 #include <wx/dcclient.h>
57 #include <wx/brush.h>
58 
61 
62 
63 ///////////////////////////////////////////////////////////////////////////////
64 /// CSelectionBroadcastSlot - a Status Bar slot that displays information about
65 /// tasks in Application Task Service
66 
67 
69 {
72 public:
75 
76  bool Create(wxWindow* parent);
77 
78  void OnPaint(wxPaintEvent& event);
79  void OnMouseEnter(wxMouseEvent& event);
80  void OnMouseLeave(wxMouseEvent& event);
81  void OnLeftDown(wxMouseEvent& event);
82 
83  void SetSelectionService(CSelectionService* selectionService);
84 
85 protected:
86  wxSize x_GetTextAreaSize();
88  string x_StatusTooltip(CSelectionEvent::EObjMatchPolicy fObj, CSelectionEvent::EIdMatchPolicy fId);
89 
91 
92  void x_Update();
93 
94 protected:
95  void x_OnSelectionEvent(CEvent*);
96 
97  wxBoxSizer* m_Sizer;
98  wxStaticText* m_TextItem;
99 
101 
102  wxString m_Text; // current status text
103 
104  bool m_Hot; // hot track (mouse inside)
105  bool m_Idle; // no running tasks
106 };
107 
109  : m_ActiveClient(NULL)
110  , m_SrvLocator(NULL)
111  , mf_AutoBroadcast(true)
112  , m_StatusBarSlot(nullptr)
113 {
114 }
115 
116 
118 {
119 }
120 
121 
123 {
124  LOG_POST(Info << "Initializing Selection Service...");
125 
126  LoadSettings();
127  LOG_POST(Info << "Finished initializing Selection Service");
128 }
129 
130 
131 void CSelectionService::InitStatusBar(wxWindow* parent)
132 {
134 
136  m_StatusBarSlot->Create(parent);
137 
138  sb_srv->InsertSlot(1, m_StatusBarSlot, m_StatusBarSlot->GetSize().x);
139  m_StatusBarSlot->Show();
140 
142 }
143 
144 
146 {
147  LOG_POST(Info << "Shutting down Selection Service...");
148 
149  if (m_StatusBarSlot)
151  m_StatusBarSlot = 0;
152 
153  while (!m_Clients.empty())
154  DetachClient(m_Clients.back());
155 
156  SaveSettings();
157 
158  LOG_POST(Info << "Finished shutting down Selection Service");
159 }
160 
161 
163 {
164  TClients::const_iterator it = std::find(m_Clients.begin(), m_Clients.end(), client);
165  if( it == m_Clients.end() ){
166  m_Clients.push_back(client);
167  client->SetSelectionService(this);
168 
171  client)));
172  } else {
173  ERR_POST("CSelectionService::AttachClient() - client already registered");
174  }
175 }
176 
177 
179 {
180  TClients::iterator it = std::find(m_Clients.begin(), m_Clients.end(), client);
181  if(it != m_Clients.end()) {
182  m_Clients.erase(it);
183  client->SetSelectionService(NULL);
184  if(m_ActiveClient == client)
186 
189  client)));
190  } else {
191  ERR_POST("CSelectionService::DetachClient() - client is not attached");
192  }
193 }
194 
196 {
197  TClients::const_iterator it = std::find( m_Clients.begin(), m_Clients.end(), client );
198  return it != m_Clients.end();
199 }
200 
201 
203 {
204  if( active != m_ActiveClient ){
205  m_ActiveClient = active;
206 
209  active)));
210 
211  if (m_ActiveClient) {
214  m_ActiveClient)));
215  }
216  }
217 }
218 
220 {
221  clients = m_Clients;
222 }
223 
225 {
226  static bool fReentry = false;
227  if (fReentry)
228  return;
229  CBoolGuard _guard(fReentry);
230 
231  try {
233  _ASSERT(srv);
234 
235  CRef<CGBWorkspace> ws = srv->GetGBWorkspace();
236  if (ws) {
238  // broadcast to all documents
239  vector<CGBProjectHandle::TId> loaded = ws->GetLoadedProjects();
240  ITERATE(vector<CGBProjectHandle::TId>, it, loaded) {
241  CGBDocument* doc = dynamic_cast<CGBDocument*>(ws->GetProjectFromId(*it));
242  if (doc) {
243  x_Broadcast(evt, source, doc->x_GetViews());
244  }
245  }
246  }
247  else {
248  CGBDocument* doc = dynamic_cast<CGBDocument*>(ws->GetProjectFromScope(evt.GetScope()));
249  // _ASSERT(doc); Search view doesn't have related project
250  if (doc)
251  x_Broadcast(evt, source, doc->x_GetViews());
252  }
253  }
254  } NCBI_CATCH("CSelectionService::Broadcast()");
255 }
256 
258 {
259  if (source && mf_AutoBroadcast)
260  source->BroadcastSelection();
261 
264  source)));
265 }
266 
268 {
269  if (m_ActiveClient)
271 }
272 
274 {
275  if (m_ActiveClient)
277 }
278 
279 void CSelectionService::GetActiveObjects(vector<TConstScopedObjects>& sel)
280 {
281  if (m_ActiveClient)
283 }
284 
286 {
287  mf_AutoBroadcast = pAuto;
288 }
289 
291  CGBDocument::TViews& views)
292 {
294  IProjectView* view = &**it;
295  if(source != static_cast<ISelectionClient*>(view)) {
296  ISelectionClient* sel_client = dynamic_cast<ISelectionClient*>(view);
297  if(sel_client) {
298  sel_client->SetSelection(evt);
299  }
300  }
301  }
302 }
303 
304 
305 void CSelectionService::SetRegistryPath(const string& reg_path)
306 {
307  m_RegPath = reg_path;
308 }
309 
310 
311 static const char* kObjMatchPolicy = "ObjMatchPolicy";
312 static const char* kIdMatchPolicy = "IdMatchPolicy";
313 static const char* kMatchByProduct = "MatchByProduct";
314 static const char* kAutoBroadcast = "AutoBroadcast";
315 static const char* kInterDocBroadcast = "InterDocBroadcast";
316 static const char* kMatchAlnLocs = "MatchAlnLocs";
317 static const char* kTreeBroadcastProperties = "TreeBroadcastProperties";
318 static const char* kTreeBroadcastOneToOne = "TreeBroadcastOneToOne";
319 
321 {
322  if(! m_RegPath.empty()) {
324  CRegistryWriteView view = gui_reg.GetWriteView(m_RegPath);
325 
329  //view.Set(kAutoBroadcast, CSelectionEvent::sm_AutoBroadcast);
333 
336  }
337 }
338 
339 
341 {
342  if(! m_RegPath.empty()) {
344  CRegistryReadView view = gui_reg.GetReadView(m_RegPath);
345 
347  value = (value < 2) ? value : 0;
349 
351  value = (value < 2) ? value : 0;
353 
358 
364 
366  // Set default values if tree broadcast criteria have not yet been added to the registry.
367  if (!view.HasField(kTreeBroadcastProperties)) {
369  CSelectionEvent::sm_TreeBroadcastProperties.push_back("fullasm_id");
370  CSelectionEvent::sm_TreeBroadcastProperties.push_back("asm_accession");
374  }
375  else {
377  }
379  }
380 }
381 
382 
384 {
385  m_SrvLocator = srv_locator;
386 }
387 
388 ///////////////////////////////////////////////////////////////////////////////
389 /// CSelectionBroadcastSlot
390 
391 
392 BEGIN_EVENT_TABLE(CSelectionBroadcastSlot, wxPanel)
394  EVT_ENTER_WINDOW(CSelectionBroadcastSlot::OnMouseEnter)
395  EVT_LEAVE_WINDOW(CSelectionBroadcastSlot::OnMouseLeave)
397  EVT_LEFT_DCLICK(CSelectionBroadcastSlot::OnLeftDown)
399 
402  CSelectionServiceEvent::eClientAttached, CSelectionServiceEvent::eSelectionChanged,
403  &CSelectionBroadcastSlot::x_OnSelectionEvent)
405 
407  : m_Sizer(NULL)
408  , m_TextItem(NULL)
409  , m_SelectionService(NULL)
410  , m_Hot(false)
411  , m_Idle(false)
412 {
413 }
414 
416 {
417  if (selectionService) {
418  m_SelectionService = selectionService;
420  } else {
421  if (m_SelectionService) {
423  m_SelectionService = 0;
424  }
425  }
426  x_Update();
427 }
428 
430 {
431  x_Update();
432 }
433 
434 static const int kTextOffX = 4;
435 static const int kTextOffY = 2;
436 
437 bool CSelectionBroadcastSlot::Create( wxWindow* parent )
438 {
439  long style = wxCLIP_CHILDREN | wxBORDER_NONE;
440 
441  if( wxPanel::Create(parent, wxID_ANY, wxDefaultPosition, wxSize(), style) ){
442  Hide();
443  SetBackgroundStyle(wxBG_STYLE_CUSTOM);
444 
445  /*
446  wxSize text_sz = x_GetTextAreaSize();
447  m_Sizer = new wxBoxSizer( wxHORIZONTAL );
448 
449  // create a Spacer for rendering text
450  m_TextItem = m_Sizer->Add( text_sz.x, text_sz.y, 1, wxEXPAND | wxFIXED_MINSIZE );
451 
452  SetSizer(m_Sizer);
453  */
454 
455  m_TextItem = new wxStaticText(
456  this, wxID_ANY, "XXXXXXX",
457  wxDefaultPosition, wxDefaultSize,
458  wxALIGN_CENTRE_HORIZONTAL | wxST_NO_AUTORESIZE
459  );
460  Fit();
461 
462  //SetSize(text_sz);
463  wxSize sz = GetSize();
464  SetMinSize(sz);
465 
466  m_TextItem->Bind( wxEVT_ENTER_WINDOW, &CSelectionBroadcastSlot::OnMouseEnter, this );
467  m_TextItem->Bind( wxEVT_LEAVE_WINDOW, &CSelectionBroadcastSlot::OnMouseLeave, this );
468  m_TextItem->Bind( wxEVT_LEFT_DOWN, &CSelectionBroadcastSlot::OnLeftDown, this );
469  m_TextItem->Bind( wxEVT_LEFT_DCLICK, &CSelectionBroadcastSlot::OnLeftDown, this );
470 
471  //m_TextItem->Hide();
472  return true;
473  }
474  return false;
475 }
476 
477 
478 // calculate the minimal area size sufficient for displaying text
480 {
482 
483  wxClientDC dc( this );
484  dc.SetFont( GetFont() );
485  wxString wx_s = ToWxString( s );
486 
487  wxSize size;
488  dc.GetTextExtent( wx_s, &size.x, &size.y );
489 
490  size.x += 2 * kTextOffX;
491  size.y += 2 * kTextOffY;
492  return size;
493 }
494 
495 // generates a text string representing the current App Task Service state
497 {
498  string s;
499  /*
500  if( fObj == CSelectionEvent::eAllIds ){
501  s += "ALL IDS";
502  } else {
503  s += "ONE ID";
504  }
505 
506  s += ";";
507  */
508 
509  if( (fId == CSelectionEvent::eExact) && (fObj == CSelectionEvent::eAllIds) ){
510  s += "EXACT";
511  } else {
512  s += "RELAXED";
513  }
514 
515  return s;
516 }
517 
519 {
520  string s;
521 
522  if( fId == CSelectionEvent::eExact ){
523  s += "Exact molecule id matching for selection broadcasting is set";
524  } else {
525  s += "Molecule versions not used for matching of selection broadcasts";
526  }
527 
528  return s;
529 }
530 
532 {
533  m_Text = wxT("");
534 
535  wxString tooltip;
536 
537  if( m_SelectionService ){
540 
541  string s = x_StatusText( obj_match, id_match );
542  m_Text = ToWxString(s);
543 
544  tooltip = ToWxString( x_StatusTooltip( obj_match, id_match ) );
545  }
546  tooltip += wxT("\n\nClick to see Broadcast Options");
547 
548 
549  m_TextItem->SetLabelText( m_Text );
550  m_TextItem->SetToolTip( tooltip );
551 
552  const wxColour back_cl = CStatusBar::GetBackColor( m_Hot );
553 
554  wxColor text_cl = CStatusBar::GetTextColor( m_Hot );
555  if(
558  ){
559  text_cl = *wxRED;
560  }
561 
562  m_TextItem->SetBackgroundColour( back_cl );
563  m_TextItem->SetForegroundColour( text_cl );
564 
565  Layout();
566  Refresh();
567 }
568 
569 
570 void CSelectionBroadcastSlot::OnPaint(wxPaintEvent& event)
571 {
572  wxPaintDC dc(this);
573 
574  // fill background
575  wxRect rc = GetRect();
576  rc.x = rc.y = 0;
577  wxColour back_cl = CStatusBar::GetBackColor(m_Hot);
578  wxBrush brush(back_cl);
579  dc.SetBrush(brush);
580  dc.SetPen(*wxTRANSPARENT_PEN);
581 
582  dc.DrawRectangle(rc);
583 
584  // draw text
585  //rc = m_TextItem->GetRect();
586  rc = this->GetRect();
587 
588  // set text font
589  wxFont font = GetFont();
590  font.SetUnderlined(m_Hot);
591  dc.SetFont(font);
592 
593  // set text color
594  wxColor cl = CStatusBar::GetTextColor(m_Hot);
595  //wxColor text_cl = m_Idle ? GetAverage(cl, back_cl, 0.5) : cl;
596  const wxColor& text_cl =
598  dc.SetTextForeground(text_cl);
599 
600  // prepare and render the text
601  int av_w = rc.width - kTextOffX * 2;
602  wxString s = TruncateText(dc, m_Text, av_w);
603 
604  int w = 0, h = 0;
605  dc.GetTextExtent(s, &w, &h);
606  int pos_x = rc.x + kTextOffX;
607  int pos_y = rc.y + (rc.height - h) / 2;
608 #if defined(__WXOSX_CARBON__) || defined(__WXMAC_CARBON__)
609  pos_y-=3;
610 #endif
611 
612  dc.DrawText(s, pos_x, pos_y);
613 }
614 
615 
616 void CSelectionBroadcastSlot::OnMouseEnter(wxMouseEvent& event)
617 {
618  m_Hot = true;
619 
620  x_Update();
621 }
622 
623 
624 void CSelectionBroadcastSlot::OnMouseLeave(wxMouseEvent& event)
625 {
626  m_Hot = false;
627 
628  x_Update();
629 }
630 
631 
632 void CSelectionBroadcastSlot::OnLeftDown(wxMouseEvent& event)
633 {
635  evt.SetEventObject(this);
636  GetEventHandler()->ProcessEvent(evt);
637 }
638 
639 
640 
User-defined methods of the data storage class.
CEventHandler.
CEvent - generic event implementation TODO TODO - Attachments.
Definition: event.hpp:86
CGBDocument.
Definition: document.hpp:113
TViews & x_GetViews(void)
Definition: document.cpp:394
vector< CIRef< IProjectView > > TViews
Definition: document.hpp:131
CRegistryWriteView GetWriteView(const string &section)
get a read-write view at a particular level.
Definition: registry.cpp:462
static CGuiRegistry & GetInstance()
access the application-wide singleton
Definition: registry.cpp:400
CRegistryReadView GetReadView(const string &section) const
get a read-only view at a particular level.
Definition: registry.cpp:428
CProjectService - a service providing API for operations with Workspaces and Projects.
class CRegistryReadView provides a nested hierarchical view at a particular key.
Definition: reg_view.hpp:58
int GetInt(const string &key, int default_val=0) const
access a named key at this level, with no recursion
Definition: reg_view.cpp:230
bool GetBool(const string &key, bool default_val=false) const
Definition: reg_view.cpp:241
bool HasField(const string &key) const
Does a field with this section and key exist in this view?
Definition: reg_view.cpp:352
void GetStringVec(const string &key, vector< string > &val) const
Definition: reg_view.cpp:263
void Set(const string &key, int val)
access a named key at this level, with no recursion
Definition: reg_view.cpp:533
CSelectionBroadcastSlot - a Status Bar slot that displays information about tasks in Application Task...
void OnPaint(wxPaintEvent &event)
void OnMouseLeave(wxMouseEvent &event)
CSelectionService * m_SelectionService
string x_StatusText(CSelectionEvent::EObjMatchPolicy fObj, CSelectionEvent::EIdMatchPolicy fId)
void SetSelectionService(CSelectionService *selectionService)
bool Create(wxWindow *parent)
string x_StatusTooltip(CSelectionEvent::EObjMatchPolicy fObj, CSelectionEvent::EIdMatchPolicy fId)
void OnMouseEnter(wxMouseEvent &event)
void OnLeftDown(wxMouseEvent &event)
CSelectionEvent CSelectionEvent is used for broadcasting selection between views.
Definition: obj_event.hpp:68
static bool sm_MatchByProduct
Definition: obj_event.hpp:209
static EObjMatchPolicy sm_ObjMatchPolicy
Definition: obj_event.hpp:206
static bool sm_TreeBroadcastOneToOne
Node properties used to compare trees when broadcasting.
Definition: obj_event.hpp:216
static bool sm_InterDocBroadcast
Definition: obj_event.hpp:211
static bool sm_MatchAlnLocs
Definition: obj_event.hpp:208
static bool sm_AutoBroadcast
Definition: obj_event.hpp:210
static vector< string > sm_TreeBroadcastProperties
broadcast sel. between documents
Definition: obj_event.hpp:213
static EIdMatchPolicy sm_IdMatchPolicy
Definition: obj_event.hpp:207
objects::CScope & GetScope()
Definition: obj_event.hpp:95
virtual void SetRegistryPath(const string &path)
void GetClients(TClients &clients)
virtual void AttachClient(ISelectionClient *client)
void x_Broadcast(CSelectionEvent &evt, ISelectionClient *source, CGBDocument::TViews &views)
vector< ISelectionClient * > TClients
virtual void GetActiveObjects(TConstScopedObjects &sel)
returns objects currently active in the application, this function should be used for obtaining argum...
IServiceLocator * m_SrvLocator
virtual bool IsAttached(ISelectionClient *client) const
void SetAutoBroadcast(bool pAuto)
virtual void DetachClient(ISelectionClient *client)
virtual void InitService()
virtual void SaveSettings() const
CSelectionBroadcastSlot * m_StatusBarSlot
virtual void GetCurrentSelection(TConstScopedObjects &sel)
returns objects currently selected in the application, this function should be used for obtaining arg...
void InitStatusBar(wxWindow *parent)
virtual void Broadcast(CSelectionEvent &evt, ISelectionClient *source)
request broadcasting of the given event, Broadcast() notifies observers about changes in selection (d...
virtual void LoadSettings()
virtual void OnSelectionChanged(ISelectionClient *source)
notifies Service and its observers about changes in selection
ISelectionClient * m_ActiveClient
virtual void SetServiceLocator(IServiceLocator *locator)
virtual void ShutDownService()
virtual void OnActiveClientChanged(ISelectionClient *active)
this function is called by GUI components to notify server
static wxColour GetTextColor(bool hot)
static wxColour GetBackColor(bool hot)
class IProjectView defines the abstract interface for views observing projects.
ISelectionClient - represents an object that support a notion of selection.
virtual void SetSelection(CSelectionEvent &evt)=0
set broadcasted selection
virtual void GetSelection(TConstScopedObjects &objects) const =0
shall return data objects representing selected things, return one data object for every selected thi...
virtual void GetActiveObjects(TConstScopedObjects &objects) const
IServiceLocator - an abstract mechanism for locating services.
Definition: service.hpp:71
@ eCmdBroadcastOptions
Definition: commands.hpp:103
#define true
Definition: bool.h:35
#define false
Definition: bool.h:36
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
#define NULL
Definition: ncbistd.hpp:225
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
#define NCBI_CATCH(message)
Catch CExceptions as well This macro is deprecated - use *_X or *_XX variant instead of it.
Definition: ncbiexpt.hpp:580
void Info(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1185
CIRef< T > GetServiceByType()
retrieves a typed reference to a service, the name of C++ type is used as the name of the service.
Definition: service.hpp:91
virtual void InsertSlot(int index, wxWindow *slot, int width=50)=0
virtual void RemoveListener(CEventHandler *listener)
Remove a listener.
void Post(CRef< CEvent > evt, EDispatch disp_how=eDispatch_Default, int pool_name=ePool_Default)
Handles an event asynchronously (process and/or dispatch).
#define END_EVENT_MAP()
Ends definition of Command Map.
#define BEGIN_EVENT_MAP(thisClass, baseClass)
Begins definition of Command Map for CEventHandler-derived class.
virtual void AddListener(CEventHandler *listener, int pool_name=ePool_Default)
Add a listener.
vector< SConstScopedObject > TConstScopedObjects
Definition: objects.hpp:65
virtual bool Send(CEvent *evt, EDispatch disp_how=eDispatch_Default, int pool_name=ePool_Default)
Sends an event synchronously.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define NCBI_GUICORE_EXPORT
Definition: gui_export.h:508
END_EVENT_TABLE()
#define wxT(x)
Definition: muParser.cpp:41
const struct ncbi::grid::netcache::search::fields::SIZE size
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
const CharType(& source)[N]
Definition: pointer.h:1149
#define nullptr
Definition: ncbimisc.hpp:45
wxEVT_COMMAND_MENU_SELECTED
USING_SCOPE(objects)
static const int kTextOffX
static const char * kMatchByProduct
static const char * kTreeBroadcastProperties
static const int kTextOffY
static const char * kObjMatchPolicy
ON_EVENT_RANGE(CSelectionServiceEvent, CSelectionServiceEvent::eClientAttached, CSelectionServiceEvent::eSelectionChanged, &CSelectionBroadcastSlot::x_OnSelectionEvent) CSelectionBroadcastSlot
CSelectionBroadcastSlot.
static const char * kIdMatchPolicy
static const char * kInterDocBroadcast
static const char * kTreeBroadcastOneToOne
static const char * kAutoBroadcast
static const char * kMatchAlnLocs
static static static wxID_ANY
static CNamedPipeClient * client
#define _ASSERT
wxString ToWxString(const string &s)
Definition: wx_utils.hpp:173
wxString TruncateText(wxDC &dc, const wxString &s, int w, Ewx_Truncate trunc=ewxTruncate_Ellipsis)
truncates given string so that its length is less or equal "w" "trunc" controls truncation,...
Definition: wx_utils.cpp:878
Modified on Mon May 27 04:37:44 2024 by modify_doxy.py rev. 669887