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

Go to the SVN repository for this file.

1 /* $Id: viewer_window_base.cpp 92491 2021-01-26 18:35:10Z grichenk $
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: Paul Thiessen
27 *
28 * File Description:
29 * base GUI functionality for viewers
30 *
31 * ===========================================================================
32 */
33 
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbistd.hpp>
36 
37 #include <memory>
38 
40 
41 #include "viewer_window_base.hpp"
42 #include "viewer_base.hpp"
43 #include "sequence_display.hpp"
44 #include "messenger.hpp"
45 #include "cn3d_threader.hpp"
46 #include "alignment_manager.hpp"
47 #include "cn3d_tools.hpp"
48 #include "pattern_dialog.hpp"
49 
50 // the application icon (under Windows it is in resources)
51 #if defined(__WXGTK__) || defined(__WXMAC__)
52  #include "cn3d42App.xpm"
53 #endif
54 
56 
57 
58 BEGIN_SCOPE(Cn3D)
59 
60 ViewerWindowBase::ViewerWindowBase(ViewerBase *parentViewer, const wxPoint& pos, const wxSize& size) :
61  wxFrame(GlobalTopWindow(), wxID_HIGHEST + 10, "", pos, size,
62  wxDEFAULT_FRAME_STYLE
63 #if defined(__WXMSW__)
64  | wxFRAME_TOOL_WINDOW
65  | wxFRAME_NO_TASKBAR
66  | wxFRAME_FLOAT_ON_PARENT
67 #endif
68  ),
69  viewerWidget(NULL), viewer(parentViewer)
70 {
71  if (!parentViewer) ERRORMSG("ViewerWindowBase::ViewerWindowBase() - got NULL pointer");
72 
73  SetSizeHints(200, 150);
74  SetIcon(wxICON(cn3d));
75 
76  // status bar with two fields - first is for id/loc, second is for general status line
77  CreateStatusBar(2);
78  int widths[2] = { 175, -1 };
79  SetStatusWidths(2, widths);
80 
81  viewerWidget = new SequenceViewerWidget(this);
82  SetupFontFromRegistry();
83 
84  menuBar = new wxMenuBar;
85  viewMenu = new wxMenu;
86  viewMenu->Append(MID_SHOW_TITLES, "Show &Titles");
87  //menu->Append(MID_HIDE_TITLES, "&Hide Titles");
88  viewMenu->Append(MID_SHOW_GEOM_VLTNS, "Show &Geometry Violations", "", true);
89  viewMenu->Append(MID_FIND_PATTERN, "Find &Pattern");
90  viewMenu->AppendSeparator();
91  viewMenu->Append(MID_CACHE_HIGHLIGHTS, "&Cache Highlights");
92  viewMenu->Append(MID_RESTORE_CACHED_HIGHLIGHTS, "Rest&ore Cached Highlights");
93  menuBar->Append(viewMenu, "&View");
94 
95  editMenu = new wxMenu;
96  editMenu->Append(MID_ENABLE_EDIT, "&Enable Editor", "", true);
97  editMenu->Append(MID_UNDO, "Undo\tCtrl-Z");
98 #ifndef __WXMAC__
99  editMenu->Append(MID_REDO, "Redo\tShift-Ctrl-Z");
100 #else
101  // mac commands apparently don't recognize shift?
102  editMenu->Append(MID_REDO, "Redo");
103 #endif
104  editMenu->AppendSeparator();
105  editMenu->Append(MID_SPLIT_BLOCK, "&Split Block", "", true);
106  editMenu->Append(MID_MERGE_BLOCKS, "&Merge Blocks", "", true);
107  editMenu->Append(MID_CREATE_BLOCK, "&Create Block", "", true);
108  editMenu->Append(MID_DELETE_BLOCK, "&Delete Block", "", true);
109  editMenu->AppendSeparator();
110  editMenu->Append(MID_SYNC_STRUCS, "Sy&nc Structure Colors");
111  editMenu->Append(MID_SYNC_STRUCS_ON, "&Always Sync Structure Colors", "", true);
112  menuBar->Append(editMenu, "&Edit");
113 
114  mouseModeMenu = new wxMenu;
115  mouseModeMenu->Append(MID_SELECT_RECT, "&Select Rectangle", "", true);
116  mouseModeMenu->Append(MID_SELECT_COLS, "Select &Columns", "", true);
117  mouseModeMenu->Append(MID_SELECT_ROWS, "Select &Rows", "", true);
118  mouseModeMenu->Append(MID_SELECT_BLOCKS, "Select &Blocks", "", true);
119  mouseModeMenu->Append(MID_DRAG_HORIZ, "&Horizontal Drag", "", true);
120  menuBar->Append(mouseModeMenu, "&Mouse Mode");
121 
122  // accelerators for special mouse mode keys
123  wxAcceleratorEntry entries[5];
124  entries[0].Set(wxACCEL_NORMAL, 's', MID_SELECT_RECT);
125  entries[1].Set(wxACCEL_NORMAL, 'c', MID_SELECT_COLS);
126  entries[2].Set(wxACCEL_NORMAL, 'r', MID_SELECT_ROWS);
127  entries[3].Set(wxACCEL_NORMAL, 'b', MID_SELECT_BLOCKS);
128  entries[4].Set(wxACCEL_NORMAL, 'h', MID_DRAG_HORIZ);
129  wxAcceleratorTable accel(5, entries);
130  SetAcceleratorTable(accel);
131 
132  justificationMenu = new wxMenu;
133  justificationMenu->Append(MID_LEFT, "&Left", "", true);
134  justificationMenu->Append(MID_RIGHT, "&Right", "", true);
135  justificationMenu->Append(MID_CENTER, "&Center", "", true);
136  justificationMenu->Append(MID_SPLIT, "&Split", "", true);
137  menuBar->Append(justificationMenu, "Unaligned &Justification");
138 
139  // set default initial modes
140  viewerWidget->SetMouseMode(SequenceViewerWidget::eSelectRectangle);
141  menuBar->Check(MID_SELECT_RECT, true);
142  menuBar->Check(MID_SPLIT, true);
143  currentJustification = BlockMultipleAlignment::eSplit;
144  viewerWidget->TitleAreaOn();
145  menuBar->Check(MID_SYNC_STRUCS_ON, true);
146  EnableBaseEditorMenuItems(false);
147  menuBar->Check(MID_SHOW_GEOM_VLTNS, false); // start with gv's off
148 }
149 
151 {
152  if (viewer) viewer->GUIDestroyed();
153 }
154 
156 {
157  // get font info from registry, and create wxFont
158  string nativeFont;
160  unique_ptr<wxFont> font(wxFont::New(wxString(nativeFont.c_str())));
161  if (!font.get() || !font->Ok())
162  {
163  ERRORMSG("ViewerWindowBase::SetupFontFromRegistry() - error setting up font");
164  return;
165  }
166  viewerWidget->SetCharacterFont(font.release());
167 }
168 
170 {
171  int i;
173  menuBar->Enable(i, enabled);
174  menuBar->Enable(MID_DRAG_HORIZ, enabled);
175  if (!enabled) CancelBaseSpecialModesExcept(-1);
176  menuBar->Enable(MID_UNDO, false);
177  menuBar->Enable(MID_REDO, false);
181 }
182 
183 void ViewerWindowBase::NewDisplay(SequenceDisplay *display, bool enableSelectByColumn)
184 {
185  viewerWidget->AttachAlignment(display);
187  menuBar->EnableTop(menuBar->FindMenu("Edit"), display->IsEditable());
188  menuBar->EnableTop(menuBar->FindMenu("Unaligned Justification"), display->IsEditable());
189  menuBar->Enable(MID_SELECT_COLS, enableSelectByColumn);
191 }
192 
194 {
195  int vsX, vsY; // to preserve scroll position
196  viewerWidget->GetScroll(&vsX, &vsY);
197  viewerWidget->AttachAlignment(display, vsX, vsY);
198  menuBar->EnableTop(menuBar->FindMenu("Edit"), display->IsEditable());
199  menuBar->EnableTop(menuBar->FindMenu("Unaligned Justification"), display->IsEditable());
203 }
204 
205 void ViewerWindowBase::OnTitleView(wxCommandEvent& event)
206 {
207  TRACEMSG("in OnTitleView()");
208  switch (event.GetId()) {
209  case MID_SHOW_TITLES:
210  viewerWidget->TitleAreaOn(); break;
211  case MID_HIDE_TITLES:
212  viewerWidget->TitleAreaOff(); break;
213  }
214 }
215 
216 void ViewerWindowBase::OnEditMenu(wxCommandEvent& event)
217 {
218  bool turnEditorOn = menuBar->IsChecked(MID_ENABLE_EDIT);
219 
220  switch (event.GetId()) {
221 
222  case MID_ENABLE_EDIT:
223  if (turnEditorOn) {
224  TRACEMSG("turning on editor");
225  if (!RequestEditorEnable(true)) {
226  menuBar->Check(MID_ENABLE_EDIT, false);
227  break;
228  }
230  viewer->GetCurrentDisplay()->AddBlockBoundaryRows(); // add before push!
231  viewer->EnableStacks(); // start up undo/redo stack system
232  ProcessCommand(MID_DRAG_HORIZ); // switch to drag mode
233  } else {
234  TRACEMSG("turning off editor");
235  if (!RequestEditorEnable(false)) { // cancelled
236  menuBar->Check(MID_ENABLE_EDIT, true);
237  break;
238  }
241  if (!(menuBar->IsChecked(MID_SELECT_COLS) || menuBar->IsChecked(MID_SELECT_ROWS) ||
242  menuBar->IsChecked(MID_SELECT_BLOCKS)))
243  ProcessCommand(MID_SELECT_RECT);
244  }
245  break;
246 
247  case MID_UNDO:
248  TRACEMSG("undoing...");
249  viewer->Undo();
252  break;
253 
254  case MID_REDO:
255  TRACEMSG("redoing...");
256  viewer->Redo();
259  break;
260 
261  case MID_SPLIT_BLOCK:
263  if (DoSplitBlock())
264  SetCursor(*wxCROSS_CURSOR);
265  else
266  SplitBlockOff();
267  break;
268 
269  case MID_MERGE_BLOCKS:
271  if (DoMergeBlocks()) {
272  SetCursor(*wxCROSS_CURSOR);
275  } else
276  MergeBlocksOff();
277  break;
278 
279  case MID_CREATE_BLOCK:
281  if (DoCreateBlock()) {
282  SetCursor(*wxCROSS_CURSOR);
285  } else
286  CreateBlockOff();
287  break;
288 
289  case MID_DELETE_BLOCK:
291  if (DoDeleteBlock())
292  SetCursor(*wxCROSS_CURSOR);
293  else
294  DeleteBlockOff();
295  break;
296 
297  case MID_SYNC_STRUCS:
299  break;
300  }
301 }
302 
303 void ViewerWindowBase::OnMouseMode(wxCommandEvent& event)
304 {
305  const wxMenuItemList& items = mouseModeMenu->GetMenuItems();
306  for (unsigned int i=0; i<items.GetCount(); ++i)
307  items.Item(i)->GetData()->Check(
308  (items.Item(i)->GetData()->GetId() == event.GetId()) ? true : false);
309 
310  switch (event.GetId()) {
311  case MID_SELECT_RECT:
313  case MID_SELECT_COLS:
315  case MID_SELECT_ROWS:
317  case MID_SELECT_BLOCKS:
319  case MID_DRAG_HORIZ:
321  }
322 }
323 
324 void ViewerWindowBase::OnJustification(wxCommandEvent& event)
325 {
326  for (int i=MID_LEFT; i<=MID_SPLIT; ++i)
327  menuBar->Check(i, (i == event.GetId()) ? true : false);
328 
329  switch (event.GetId()) {
330  case MID_LEFT:
332  case MID_RIGHT:
334  case MID_CENTER:
336  case MID_SPLIT:
338  }
340 }
341 
342 void ViewerWindowBase::OnShowGeomVltns(wxCommandEvent& event)
343 {
346 }
347 
349 {
351  ViewerBase::AlignmentList::const_iterator a, ae = alignments.end();
352  int nViolations = 0;
353  for (a=alignments.begin(); a!=ae; ++a)
354  nViolations += (*a)->ShowGeometryViolations(GeometryViolationsShown());
356  INFOMSG("Found " << nViolations << " geometry violation"
357  << ((nViolations == 1) ? "" : "s") << " in this window");
358 }
359 
360 void ViewerWindowBase::OnFindPattern(wxCommandEvent& event)
361 {
362  // remember previous pattern
363  static wxString previousPattern;
364  static wxString previousMode("Replace");
365 
366  // get pattern from user
367  PatternDialog dialog(this);
368  dialog.m_Pattern->SetValue(previousPattern);
369  dialog.m_Pattern->SetSelection(-1, -1);
370  dialog.m_Mode->SetStringSelection(previousMode);
371  int status = dialog.ShowModal();
372  wxString pattern = dialog.m_Pattern->GetValue();
373  if (status != wxID_OK || pattern.size() == 0)
374  return;
375 
376  // add trailing period if not present (convenience for the user)
377  if (pattern[pattern.size() - 1] != '.') pattern += '.';
378  previousPattern = pattern;
379  previousMode = dialog.m_Mode->GetStringSelection();
380 
381  // set up highlighting
383  if (dialog.m_Mode->GetStringSelection() == "Within")
384  GlobalMessenger()->GetHighlights(&restrictTo);
385  if (dialog.m_Mode->GetStringSelection() == "Replace" || dialog.m_Mode->GetStringSelection() == "Within")
387 
388  // highlight pattern from each (unique) sequence in the display
389  map < const Sequence * , bool > usedSequences;
390  const SequenceDisplay *display = viewer->GetCurrentDisplay();
391 
392  for (unsigned int i=0; i<display->NRows(); ++i) {
393 
394  const Sequence *sequence = display->GetSequenceForRow(i);
395  if (!sequence || usedSequences.find(sequence) != usedSequences.end()) continue;
396  usedSequences[sequence] = true;
397 
398  if (!sequence->HighlightPattern(WX_TO_STD(pattern), restrictTo)) break;
399  }
400 }
401 
403 {
404  const SequenceDisplay *display = viewer->GetCurrentDisplay();
405  for (unsigned int i=0; i<display->NRows(); ++i) {
406  const Sequence *sequence = display->GetSequenceForRow(i);
407  if (sequence && sequence->identifier == identifier) {
409  break;
410  }
411  }
412 }
413 
414 void ViewerWindowBase::OnCacheHighlights(wxCommandEvent& event)
415 {
416  if (event.GetId() == MID_CACHE_HIGHLIGHTS)
418  else if (event.GetId() == MID_RESTORE_CACHED_HIGHLIGHTS)
420 }
421 
422 END_SCOPE(Cn3D)
void RestoreCachedHighlights(void)
Definition: messenger.cpp:417
void GetHighlights(MoleculeHighlightMap *copyHighlights)
Definition: messenger.cpp:424
void PostRedrawSequenceViewer(ViewerBase *viewer)
Definition: messenger.cpp:95
bool RemoveAllHighlights(bool postRedraws)
Definition: messenger.cpp:393
void PostRedrawAllSequenceViewers(void)
Definition: messenger.cpp:90
void CacheHighlights(void)
Definition: messenger.cpp:412
std::map< const MoleculeIdentifier *, std::vector< bool > > MoleculeHighlightMap
Definition: messenger.hpp:99
wxTextCtrl * m_Pattern
wxRadioBox * m_Mode
void AddBlockBoundaryRows(void)
const Sequence * GetSequenceForRow(unsigned int row) const
unsigned int NRows(void) const
void RedrawAlignedMolecules(void) const
void RemoveBlockBoundaryRows(void)
bool IsEditable(void) const
bool AttachAlignment(ViewableAlignment *newAlignment, int initX=0, int initY=0)
void GetScroll(int *vsX, int *vsY) const
void MakeCharacterVisible(int column, int row) const
eMouseMode GetMouseMode(void) const
void SetMouseMode(eMouseMode mode)
void SetCharacterFont(wxFont *font)
const MoleculeIdentifier * identifier
bool HighlightPattern(const std::string &pattern, const MoleculeHighlightMap &restrictTo) const
std::list< BlockMultipleAlignment * > AlignmentList
Definition: viewer_base.hpp:89
void SetUndoRedoMenuStates(void)
SequenceDisplay * GetCurrentDisplay(void)
void EnableStacks(void)
Definition: viewer_base.cpp:92
void GUIDestroyed(void)
Definition: viewer_base.hpp:67
void Undo(void)
void Redo(void)
const AlignmentList & GetCurrentAlignments(void) const
bool DoCreateBlock(void) const
void NewDisplay(SequenceDisplay *display, bool enableSelectByColumn)
bool DoSplitBlock(void) const
void SetupFontFromRegistry(void)
virtual bool RequestEditorEnable(bool enable)
void MakeSequenceVisible(const MoleculeIdentifier *identifier)
void OnFindPattern(wxCommandEvent &event)
SequenceViewerWidget * viewerWidget
virtual SequenceViewerWidget::eMouseMode GetMouseModeForCreateAndMerge(void)=0
BlockMultipleAlignment::eUnalignedJustification currentJustification
bool DoMergeBlocks(void) const
SequenceViewerWidget::eMouseMode prevMouseMode
void CancelBaseSpecialModesExcept(int id)
void UpdateGeometryViolations(void) const
void OnJustification(wxCommandEvent &event)
void CancelAllSpecialModesExcept(int id)
void OnEditMenu(wxCommandEvent &event)
virtual ~ViewerWindowBase(void)
virtual void EnableDerivedEditorMenuItems(bool enable)
void OnMouseMode(wxCommandEvent &event)
bool AlwaysSyncStructures(void) const
void OnShowGeomVltns(wxCommandEvent &event)
bool DoDeleteBlock(void) const
void EnableBaseEditorMenuItems(bool enabled)
void UpdateDisplay(SequenceDisplay *display)
void OnTitleView(wxCommandEvent &event)
void OnCacheHighlights(wxCommandEvent &event)
bool GeometryViolationsShown(void) const
const_iterator end() const
Definition: map.hpp:152
const_iterator find(const key_type &key) const
Definition: map.hpp:153
Definition: map.hpp:338
wxFrame * GlobalTopWindow(void)
Definition: cn3d_app.cpp:90
bool RegistryGetString(const string &section, const string &name, string *value)
Definition: cn3d_tools.cpp:263
static const std::string REG_SEQUENCE_FONT_SECTION
Definition: cn3d_tools.hpp:183
#define TRACEMSG(stream)
Definition: cn3d_tools.hpp:83
#define INFOMSG(stream)
Definition: cn3d_tools.hpp:84
static const std::string REG_FONT_NATIVE_FONT_INFO
Definition: cn3d_tools.hpp:184
#define WX_TO_STD(wxstring)
Definition: cn3d_tools.hpp:285
#define ERRORMSG(stream)
Definition: cn3d_tools.hpp:86
Include a standard set of the NCBI C++ Toolkit most basic headers.
#define NULL
Definition: ncbistd.hpp:225
#define END_SCOPE(ns)
End the previously defined scope.
Definition: ncbistl.hpp:75
#define BEGIN_SCOPE(ns)
Define a new scope.
Definition: ncbistl.hpp:72
int i
Messenger * GlobalMessenger(void)
Definition: messenger.cpp:73
const struct ncbi::grid::netcache::search::fields::SIZE size
unsigned int a
Definition: ncbi_localip.c:102
ViewerWindowBase::OnEditMenu MID_SPLIT
USING_NCBI_SCOPE
static wxAcceleratorEntry entries[3]
#define const
Definition: zconf.h:232
Modified on Wed Sep 04 14:58:42 2024 by modify_doxy.py rev. 669887