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

Go to the SVN repository for this file.

1 /* $Id: cn3d_app.cpp 97253 2022-06-29 17:35:29Z dzhang $
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 * log and application object for Cn3D
30 *
31 * ===========================================================================
32 */
33 
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbistd.hpp>
36 #include <corelib/ncbitime.hpp> // avoids some 'CurrentTime' conflict later on...
37 #include <serial/objostr.hpp>
38 
42 #include <objects/seq/Bioseq.hpp>
46 
47 #include <algorithm>
48 #include <vector>
49 
51 
52 #ifdef __WXMSW__
53 #include <windows.h>
54 #include <wx/msw/winundef.h>
55 #endif
56 #include <wx/wx.h>
57 #include <wx/filesys.h>
58 #include <wx/fs_zip.h>
59 
60 #include "asn_reader.hpp"
61 #include "cn3d_app.hpp"
62 #include "structure_window.hpp"
63 #include "cn3d_tools.hpp"
64 #include "structure_set.hpp"
65 #include "chemical_graph.hpp"
66 #include "cn3d_glcanvas.hpp"
67 #include "opengl_renderer.hpp"
68 #include "messenger.hpp"
69 #include "alignment_manager.hpp"
70 #include "cn3d_cache.hpp"
71 #include "data_manager.hpp"
72 
73 // the application icon (under Windows it is in resources)
74 #if defined(__WXGTK__) || defined(__WXMAC__)
75  #include "cn3d42App.xpm"
76 #endif
77 
80 
81 
82 // `Main program' equivalent
83 IMPLEMENT_APP(Cn3D::Cn3DApp)
84 
85 
86 BEGIN_SCOPE(Cn3D)
87 
88 // top-level window (the main structure window)
89 static wxFrame *topWindow = NULL;
90 wxFrame * GlobalTopWindow(void) { return topWindow; }
91 
92 bool IsWindowedMode(void) { return true; }
93 
94 // Set the NCBI diagnostic streams to go to this method, which then pastes them
95 // into a wxWindow. This log window can be closed anytime, but will be hidden,
96 // not destroyed. More serious errors will bring up a dialog, so that the user
97 // will get a chance to see the error before the program halts upon a fatal error.
98 
99 class MsgFrame;
100 
102 static list < string > backLog;
103 
104 class MsgFrame : public wxFrame
105 {
106 public:
107  wxTextCtrl *logText;
109  MsgFrame(const wxString& title,
110  const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize) :
111  wxFrame(GlobalTopWindow(), wxID_HIGHEST + 5, title, pos, size,
112  wxDEFAULT_FRAME_STYLE
113 #if defined(__WXMSW__)
114  | wxFRAME_TOOL_WINDOW | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT
115 #endif
116  )
117  {
118  totalChars = 0;
119  SetIcon(wxICON(cn3d));
120  }
122 private:
123  // need to define a custom close window handler, so that window isn't actually destroyed,
124  // just hidden when user closes it with system close button
125  void OnCloseWindow(wxCloseEvent& event);
126  DECLARE_EVENT_TABLE()
127 };
128 
129 BEGIN_EVENT_TABLE(MsgFrame, wxFrame)
130  EVT_CLOSE(MsgFrame::OnCloseWindow)
132 
133 void MsgFrame::OnCloseWindow(wxCloseEvent& event)
134 {
135  if (event.CanVeto()) {
136  Show(false);
137  event.Veto();
138  } else {
139  Destroy();
140  logFrame = NULL;
141  }
142 }
143 
144 static bool dialogSevereErrors = true;
145 void SetDialogSevereErrors(bool status)
146 {
147  dialogSevereErrors = status;
148 }
149 
150 void DisplayDiagnostic(const SDiagMessage& diagMsg)
151 {
152  string errMsg;
153  diagMsg.Write(errMsg);
154 
155  // severe errors get a special error dialog
156  if (diagMsg.m_Severity >= eDiag_Error && diagMsg.m_Severity != eDiag_Trace && dialogSevereErrors) {
157  // a bug in wxWidgets makes the error message dialog non-modal w.r.t some windows; this avoids a
158  // strange recursion problem that brings up multiple error dialogs (but doesn't fix the underlying problem)
159  static bool avoidRecursion = false;
160  if (!avoidRecursion) {
161  avoidRecursion = true;
162  wxMessageDialog dlg(NULL, errMsg.c_str(), "Severe Error!", wxOK | wxCENTRE | wxICON_EXCLAMATION);
163  dlg.ShowModal();
164  avoidRecursion = false;
165  }
166  }
167 
168  // info messages and less severe errors get added to the log
169  else {
170  if (logFrame) {
171  // delete top of log if too big
172  if (logFrame->totalChars + errMsg.size() > 100000) {
173  logFrame->logText->Clear();
174  logFrame->totalChars = 0;
175  }
176  logFrame->logText->SetInsertionPoint(logFrame->logText->GetLastPosition());
177  *(logFrame->logText) << errMsg.c_str();
178  logFrame->totalChars += errMsg.size();
179  } else {
180  // if message window doesn't exist yet, store messages until later
181  backLog.push_back(errMsg.c_str());
182  }
183  }
184 }
185 
186 void RaiseLogWindow(void)
187 {
188  if (!logFrame) {
189  logFrame = new MsgFrame("Cn3D Message Log", wxPoint(500, 0), wxSize(500, 500));
190 #ifdef __WXMAC__
191  logFrame->Move(500, 20); // drop the window below the Mac menubar
192  // make empty menu for this window
193  wxMenuBar *menuBar = new wxMenuBar;
194  logFrame->SetMenuBar(menuBar);
195 #endif
196  logFrame->SetSizeHints(150, 100);
197  logFrame->logText = new wxTextCtrl(logFrame, -1, "",
198  wxPoint(0,0), logFrame->GetClientSize(), wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxHSCROLL);
199  // display any messages received before window created
200  while (backLog.size() > 0) {
201  *(logFrame->logText) << backLog.front().c_str();
202  logFrame->totalChars += backLog.front().size();
203  backLog.erase(backLog.begin());
204  }
205  }
206  logFrame->logText->ShowPosition(logFrame->logText->GetLastPosition());
207  logFrame->Show(true);
208 #if defined(__WXMSW__)
209  if (logFrame->IsIconized()) logFrame->Maximize(false);
210 #endif
211  logFrame->Raise();
212 }
213 
214 
215 BEGIN_EVENT_TABLE(Cn3DApp, wxApp /*wxGLApp*/)
216  EVT_IDLE(Cn3DApp::OnIdle)
218 
219 Cn3DApp::Cn3DApp() : wxApp() /*wxGLApp()*/
220 {
221  // setup the diagnostic stream
223  SetDiagPostLevel(eDiag_Info); // report all messages
224  SetDiagTrace(eDT_Default); // trace messages only when DIAG_TRACE env. var. is set
226 #ifdef _DEBUG
229 #else
232 #endif
233 
234  // C++ object verification
238 
239 // if (!InitGLVisual(NULL))
240 // FATALMSG("InitGLVisual failed");
241 }
242 
243 bool Cn3DApp::OnInit(void)
244 {
245  INFOMSG("Welcome to Cn3D " << CN3D_VERSION_STRING << "!");
246  INFOMSG("Built " << __DATE__ << " with wxWidgets " << wxVERSION_NUM_DOT_STRING);
247 
248 #ifdef _DEBUG
249  INFOMSG("This is a debug build");
250 #elif NDEBUG
251  INFOMSG("This is a release build");
252 #endif
253 #ifdef _USE_TEST_MMDBSRV_
254  INFOMSG("This build uses a test mmdbsrv");
255 #else
256  INFOMSG("This build uses the standard mmdbsrv");
257 #endif
258 
259  // set up command line parser
260  static const wxCmdLineEntryDesc cmdLineDesc[] = {
261  { wxCMD_LINE_SWITCH, "h", "help", "show this help message",
262  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
263  { wxCMD_LINE_SWITCH, "r", "readonly", "message file is read-only",
264  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
265  { wxCMD_LINE_SWITCH, "i", "imports", "show imports window on startup",
266  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
267  { wxCMD_LINE_SWITCH, "n", "noalign", "do not show alignment window on startup",
268  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
269  { wxCMD_LINE_SWITCH, "f", "force", "force saves to same file",
270  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
271  { wxCMD_LINE_OPTION, "m", "message", "message file",
272  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_NEEDS_SEPARATOR },
273  { wxCMD_LINE_OPTION, "a", "targetapp", "messaging target application name",
274  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_NEEDS_SEPARATOR },
275  { wxCMD_LINE_OPTION, "o", "model", "model choice: alpha, single, or PDB",
276  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_NEEDS_SEPARATOR },
277  { wxCMD_LINE_OPTION, "d", "id", "MMDB/PDB ID to load via network",
278  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_NEEDS_SEPARATOR },
279  { wxCMD_LINE_OPTION, "s", "style", "preferred favorite style",
280  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_NEEDS_SEPARATOR },
281  { wxCMD_LINE_PARAM, NULL, NULL, "input file",
282  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL},
283  { wxCMD_LINE_NONE }
284  };
285  commandLine.SetSwitchChars("-");
286  commandLine.SetDesc(cmdLineDesc);
287  commandLine.SetCmdLine(argc, argv);
288  switch (commandLine.Parse()) {
289  case 0: TRACEMSG("command line parsed successfully"); break;
290  default: return false; // exit upon either help or syntax error
291  }
292 
293  // help system loads from zip file
294  wxFileSystem::AddHandler(new wxZipFSHandler);
295 
296  // setup dirs
297  SetUpWorkingDirectories(argv[0]);
298 
299  // read dictionary
300  wxString dictFile = wxString(GetDataDir().c_str()) + "bstdt.val";
301  LoadStandardDictionary(dictFile.c_str());
302 
303  // set up registry and favorite styles (must be done before structure window creation)
304  LoadRegistry();
305 
306  // create the main frame window - must be first window created by the app
308  wxString("Cn3D ") + CN3D_VERSION_STRING, wxPoint(0,0), wxSize(500,500));
309 
310  // On the Mac, drop window down slightly so that the title bar
311  // is not under the menu bar at the top of the screen.
312 #ifdef __WXMAC__
313  structureWindow->Move(0, 20);
314 #endif
315 
316  SetTopWindow(structureWindow);
317  SetExitOnFrameDelete(true); // exit app when structure window is closed
319 
320  // show log if set to do so
321  bool showLog = false;
323  if (showLog) RaiseLogWindow();
324 
325  // set preferred style if given
326  wxString favStyle;
327  if (commandLine.Found("s", &favStyle))
329 
330  // get model type from -o
332  wxString modelStr;
333  if (commandLine.Found("o", &modelStr)) {
334  if (modelStr == "alpha")
336  else if (modelStr == "single")
338  else if (modelStr == "PDB")
339  model = eModel_type_pdb_model;
340  else
341  ERRORMSG("Model type (-o) must be one of alpha|single|PDB");
342  }
343 
344  // load file given on command line
345  if (commandLine.GetParamCount() == 1) {
346  wxString filename = commandLine.GetParam(0).c_str();
347  INFOMSG("command line file: " << filename.c_str());
348  // if -o is present, assume param is a Biostruc file
349  if (model != eModel_type_other) { // -o present
350  CNcbi_mime_asn1 *mime = CreateMimeFromBiostruc(WX_TO_STD(filename), model);
351  if (mime)
352  structureWindow->LoadData(NULL, commandLine.Found("f"), commandLine.Found("n"), mime);
353  } else {
354  structureWindow->LoadData(filename.c_str(), commandLine.Found("f"), commandLine.Found("n"));
355  }
356  }
357 
358  // if no file passed but there is -o, see if there's a -d parameter (MMDB/PDB ID to fetch)
359  else if (model != eModel_type_other) { // -o present
360  wxString id;
361  if (commandLine.Found("d", &id)) {
362  CNcbi_mime_asn1 *mime = LoadStructureViaCache(WX_TO_STD(id), model, 0);
363  if (mime)
364  structureWindow->LoadData(NULL, commandLine.Found("f"), commandLine.Found("n"), mime);
365  } else {
366  ERRORMSG("-o requires either -d or Biostruc file name");
367  }
368  }
369 
370  // if no structure loaded, show the logo
373  structureWindow->glCanvas->Refresh(false);
374  }
375 
376  // set up messaging file communication
377  wxString messageFilename;
378  if (commandLine.Found("m", &messageFilename)) {
379  wxString messageApp;
380  if (!commandLine.Found("a", &messageApp))
381  messageApp = "Listener";
383  WX_TO_STD(messageFilename), WX_TO_STD(messageApp), commandLine.Found("r"));
384  }
385 
386  // optionally open imports window, but only if any imports present
387  if (commandLine.Found("i") && structureWindow->glCanvas->structureSet &&
390 
391  // give structure window initial focus
392  structureWindow->Raise();
393  structureWindow->SetFocus();
394 
395  // hack to fix some platforms that start with initially blank window
397 
398  return true;
399 }
400 
402 {
404  SetDiagStream(&cout);
405 
406  // save registry
407  SaveRegistry();
408 
409  // remove dictionary
411 
412  // destroy log
413  if (logFrame) logFrame->Destroy();
414 
415  return 0;
416 }
417 
418 void Cn3DApp::OnIdle(wxIdleEvent& event)
419 {
420  // process pending redraws
422 
423  // call base class OnIdle to continue processing any other system idle-time stuff
424 #if wxCHECK_VERSION(2,9,0)
425  // WARNING: no idea at all if it's necessary to do any equivalent here under 2.9...
426 #else
427  wxApp::OnIdle(event);
428 #endif
429 }
430 
431 #ifdef __WXMAC__
432 // special handler for open file apple event
433 void Cn3DApp::MacOpenFile(const wxString& filename)
434 {
435  if (filename.size() > 0) {
436  INFOMSG("apple open event file: " << filename);
437  structureWindow->LoadData(filename, false, commandLine.Found("n"));
438  }
439 }
440 #endif
441 
442 END_SCOPE(Cn3D)
User-defined methods of the data storage class.
User-defined methods of the data storage class.
#define static
User-defined methods of the data storage class.
void LoadStandardDictionary(const char *filename)
void DeleteStandardDictionary(void)
void ShowUpdateWindow(void) const
unsigned int NUpdates(void) const
int OnExit(void)
Definition: cn3d_app.cpp:401
wxCmdLineParser commandLine
Definition: cn3d_app.hpp:72
bool OnInit(void)
Definition: cn3d_app.cpp:243
StructureWindow * structureWindow
Definition: cn3d_app.hpp:65
void OnIdle(wxIdleEvent &event)
Definition: cn3d_app.cpp:418
OpenGLRenderer * renderer
void FakeOnSize(void)
StructureSet * structureSet
void ProcessRedraws(void)
Definition: messenger.cpp:123
wxTextCtrl * logText
Definition: cn3d_app.cpp:107
MsgFrame(const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize)
Definition: cn3d_app.cpp:109
int totalChars
Definition: cn3d_app.cpp:108
~MsgFrame(void)
Definition: cn3d_app.cpp:121
void OnCloseWindow(wxCloseEvent &event)
Definition: cn3d_app.cpp:133
void AttachStructureSet(StructureSet *targetStructureSet)
AlignmentManager * alignmentManager
void SetPreferredFavoriteStyle(const std::string &s)
void SetupFileMessenger(const std::string &messageFilename, const std::string &messageApp, bool readOnly)
Cn3DGLCanvas * glCanvas
bool LoadData(const char *filename, bool force, bool noAlignmentWindow, ncbi::objects::CNcbi_mime_asn1 *mimeData=NULL)
USING_SCOPE(objects)
static list< string > backLog
Definition: cn3d_app.cpp:102
void DisplayDiagnostic(const SDiagMessage &diagMsg)
Definition: cn3d_app.cpp:150
void SetDialogSevereErrors(bool status)
Definition: cn3d_app.cpp:145
void RaiseLogWindow(void)
Definition: cn3d_app.cpp:186
wxFrame * GlobalTopWindow(void)
Definition: cn3d_app.cpp:90
static wxFrame * topWindow
Definition: cn3d_app.cpp:89
static bool dialogSevereErrors
Definition: cn3d_app.cpp:144
static MsgFrame * logFrame
Definition: cn3d_app.cpp:101
USING_NCBI_SCOPE
Definition: cn3d_app.cpp:78
bool IsWindowedMode(void)
Definition: cn3d_app.cpp:92
CNcbi_mime_asn1 * LoadStructureViaCache(const std::string &uid, ncbi::objects::EModel_type modelType, int assemblyId)
Definition: cn3d_cache.cpp:255
void SetUpWorkingDirectories(const char *argv0)
Definition: cn3d_tools.cpp:333
void LoadRegistry(void)
Definition: cn3d_tools.cpp:171
void SaveRegistry(void)
Definition: cn3d_tools.cpp:189
const string & GetDataDir(void)
Definition: cn3d_tools.cpp:330
bool RegistryGetBoolean(const string &section, const string &name, bool *value)
Definition: cn3d_tools.cpp:250
static const std::string REG_CONFIG_SECTION
Definition: cn3d_tools.hpp:158
#define TRACEMSG(stream)
Definition: cn3d_tools.hpp:83
#define INFOMSG(stream)
Definition: cn3d_tools.hpp:84
#define CN3D_VERSION_STRING
Definition: cn3d_tools.hpp:80
#define WX_TO_STD(wxstring)
Definition: cn3d_tools.hpp:285
#define ERRORMSG(stream)
Definition: cn3d_tools.hpp:86
static const std::string REG_SHOW_LOG_ON_START
Definition: cn3d_tools.hpp:161
Include a standard set of the NCBI C++ Toolkit most basic headers.
CNcbi_mime_asn1 * CreateMimeFromBiostruc(const string &filename, EModel_type model)
#define NULL
Definition: ncbistd.hpp:225
void Write(string &str, TDiagWriteFlags flags=fNone) const
Binary OR of "EDiagWriteFlags".
Definition: ncbidiag.cpp:5358
void SetDiagPostFlag(EDiagPostFlag flag)
Set the specified flag (globally).
Definition: ncbidiag.cpp:6073
EDiagSev m_Severity
Severity level.
Definition: ncbidiag.hpp:1651
void UnsetDiagTraceFlag(EDiagPostFlag flag)
Definition: ncbidiag.cpp:6094
EDiagSev SetDiagPostLevel(EDiagSev post_sev=eDiag_Error)
Set the threshold severity for posting the messages.
Definition: ncbidiag.cpp:6132
void SetDiagHandler(CDiagHandler *handler, bool can_delete=true)
Set the diagnostic handler using the specified diagnostic handler class.
Definition: ncbidiag.cpp:6291
void SetDiagTrace(EDiagTrace how, EDiagTrace dflt=eDT_Default)
Set the diagnostic trace settings.
Definition: ncbidiag.cpp:6229
void SetDiagStream(CNcbiOstream *os, bool quick_flush=true, FDiagCleanup cleanup=0, void *cleanup_data=0, const string &stream_name="")
Set diagnostic stream.
Definition: ncbidiag.cpp:8086
@ eDPF_Location
Include class and function if any.
Definition: ncbidiag.hpp:704
@ eDPF_Line
Source line.
Definition: ncbidiag.hpp:695
@ eDPF_File
File name (not full path)
Definition: ncbidiag.hpp:693
@ eDT_Default
Restores the default tracing context.
Definition: ncbidiag.hpp:1548
@ eDiag_Trace
Trace message.
Definition: ncbidiag.hpp:657
@ eDiag_Info
Informational message.
Definition: ncbidiag.hpp:651
@ eDiag_Error
Error message.
Definition: ncbidiag.hpp:653
static void SetVerifyDataGlobal(ESerialVerifyData verify)
@ eSerialVerifyData_Always
always verify (even if set not to later on)
Definition: serialdef.hpp:112
static void SetVerifyDataGlobal(ESerialVerifyData verify)
Set up default output data verification for streams created by the current process.
Definition: objostr.cpp:214
static void SetVerifyDataGlobal(ESerialVerifyData verify)
Set up default input data verification for streams created by the current process.
Definition: objistr.cpp:243
#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
EModel_type
Access to EModel_type's attributes (values, names) as defined in spec.
Definition: Model_type_.hpp:63
@ eModel_type_ncbi_all_atom
Definition: Model_type_.hpp:66
@ eModel_type_ncbi_backbone
Definition: Model_type_.hpp:65
@ eModel_type_other
Definition: Model_type_.hpp:68
@ eModel_type_pdb_model
Definition: Model_type_.hpp:67
END_EVENT_TABLE()
if(yy_accept[yy_current_state])
Messenger * GlobalMessenger(void)
Definition: messenger.cpp:73
const struct ncbi::grid::netcache::search::fields::SIZE size
Defines: CTimeFormat - storage class for time format.
SDiagMessage –.
Definition: ncbidiag.hpp:1599
Modified on Fri Sep 20 14:56:58 2024 by modify_doxy.py rev. 669887