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

Go to the SVN repository for this file.

1 /* $Id: workbench_frame.cpp 47237 2022-11-18 18:53:45Z evgeniev $
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  */
29 
30 #include <ncbi_pch.hpp>
31 
32 #include <wx/platform.h>
33 
37 
41 
42 #include <util/checksum.hpp>
46 
47 #include "pager_message_dlg.hpp"
48 
49 
50 #include <wx/menu.h>
51 
52 // For OpenGL context creation via CGLPixelFormatObj
53 // (our opengl header only includes gl.h)
54 #ifdef __WXMAC__
55 #include <OpenGL/OpenGL.h>
56 #endif
57 
59 
60 BEGIN_EVENT_TABLE( CWorkbenchFrame, CWorkbenchFrame::TParent )
62  EVT_KEY_DOWN(CWorkbenchFrame::OnKeyDown)
63  EVT_KEY_UP(CWorkbenchFrame::OnKeyUp)
64  EVT_MOVE(CWorkbenchFrame::OnMove)
65  EVT_IDLE(CWorkbenchFrame::OnIdle)
66  EVT_ACTIVATE(CWorkbenchFrame::OnActivate)
68 
69 
71 {
72 }
73 
74 
75 CWorkbenchFrame::CWorkbenchFrame( wxWindow* parent, wxWindowID id, const wxString& caption,
76  const wxPoint& pos, const wxSize& size, long style )
77 : TParent(parent, id, caption, pos, size, style),
78  m_Workbench(NULL),
79  m_DockManager(NULL),
80  m_ForwardKeyEvents(false),
81  m_IsMoving(false)
82 {
83 #ifdef __WXMAC__
84  // Some mac laptops come with both a discrete graphics card and graphics on the (intel) cpu.
85  // These can switch between cards dynamically to save power, but that causes problems at least
86  // in the current revision of the os. JIRA: GB-1636 for more details.
87  // Create and leak an opengl context to force cpu into discrete graphics mode from the start.
88  static CGLPixelFormatObj format = NULL;
89  if (!format) {
90  CGLPixelFormatAttribute attribs[1];
91  attribs[0] = static_cast<CGLPixelFormatAttribute>(0);
92  GLint num_pixel_formats = 0;
93  CGLChoosePixelFormat(attribs, &format, &num_pixel_formats);
94  _TRACE("OpenGL context created!");
95  }
96  EnableFullScreenView(false);
97 #endif
98 }
99 
101 {
102 }
103 
104 
106 {
107  m_Workbench = workbench;
108 }
109 
110 
112 {
113  // There is only 1 dockmanager, but it is set here for key events
114  // and elsewhere for updates while moving this window
115  if (manager != NULL) {
116  m_DockManager = manager;
117  m_ForwardKeyEvents = true;
118  }
119  else {
120  m_ForwardKeyEvents = false;
121  }
122 }
123 
124 bool CWorkbenchFrame::ProcessEvent(wxEvent& event)
125 {
126  // Redirect events to active child first. Stops the same event being processed repeatedly
127  static wxEventType inEvent = wxEVT_NULL;
128  if (inEvent == event.GetEventType())
129  return false;
130  inEvent = event.GetEventType();
131 
132  bool res = false;
133 
134  if(m_Workbench && event.IsCommandEvent()) {
135  wxEventType type = event.GetEventType();
136 
137  // Sometimes accelerators do not seem to get propogated in mac - this
138  // propogates the selectall (GB-2626)
139  if (event.GetId() == wxID_SELECTALL) {
140  wxWindow* focused = wxWindow::FindFocus();
141  if (focused != NULL) {
142  res = focused->GetEventHandler()->ProcessEvent(event);
143  }
144  }
145 
146  if (!res && (type == wxEVT_UPDATE_UI || type == wxEVT_COMMAND_MENU_SELECTED)) {
147  // forward commands to Workbench
148 
149  wxEvtHandler* handler = dynamic_cast<wxEvtHandler*>(m_Workbench);
150  if(handler) {
151  res = handler->ProcessEvent(event);
152  }
153  }
154  }
155 
156  if( ! res) {
157  res = TParent::ProcessEvent(event);
158  }
159 
160  inEvent = wxEVT_NULL;
161  return res;
162 }
163 
164 
165 void CWorkbenchFrame::OnCloseWindow(wxCloseEvent& event)
166 {
167  if(m_Workbench) {
168  if(event.CanVeto()) {
169  /// see whether the application can be closed now
170  bool can = m_Workbench->CanShutDown();
171  if( ! can) {
172  event.Veto();
173  return;
174  }
175  }
176  // otherwise - ask Workbench to shutdown
177  // it will eventually destroy the window, but we MUST NOT do it right now
179  }
180  SetEvtHandlerEnabled(false);
181 }
182 
183 
184 // during D&D focus changes unpredictably and often is reflected to the
185 // main frame, this is why we need to forward events back to Dock Manager
186 void CWorkbenchFrame::OnKeyDown(wxKeyEvent& event)
187 {
188  if(m_ForwardKeyEvents) {
189  m_DockManager->OnKeyDown(event);
190  } else {
191  event.Skip();
192  }
193 }
194 
195 
196 void CWorkbenchFrame::OnKeyUp(wxKeyEvent& event)
197 {
198  if(m_ForwardKeyEvents) {
199  m_DockManager->OnKeyUp(event);
200  } else {
201  event.Skip();
202  }
203 }
204 
205 void CWorkbenchFrame::OnMove(wxMoveEvent& event)
206 {
208 
209  if (!m_IsMoving) {
210  m_IsMoving = true;
211 
212 // This is to keep tooltip z order. Tips when they get focus or are
213 // brought to the front (as during a move) they can get in front of
214 // other wnidows. Not needed on MAC because it never lets the
215 // tips in front of other windows in the first place.
216 #ifndef NCBI_OS_DARWIN
217  if (m_DockManager)
219 #endif
220  }
221 }
222 
223 void CWorkbenchFrame::OnIdle(wxIdleEvent& event)
224 {
225  if (m_IsMoving) {
226 #if(wxMAJOR_VERSION==2 && wxMINOR_VERSION<9)
227  if ( !wxGetMouseState().LeftDown() ) {
228 #else
229  if ( !wxGetMouseState().LeftIsDown() ) {
230 #endif
231  m_IsMoving = false;
232 #ifndef NCBI_OS_DARWIN
233  SetFocus();
234 #endif
235  }
236  }
237 #ifdef __WXMAC__
238 
239  // Make sure the window title bar doesn't go out of bounds - above
240  // the menubar at the top of the window. This can happen when
241  // resizing after maximizing the window (especially after maximizing,
242  // closing the program, restarting, and then maximizing again)
243  // We put this in the idle event because Cocoa doesn't
244  // generate move events for these actions.
245  // (Note that if the user has multiple monitors and the monitor
246  // with the menubar is BELOW the other monitor, you will not
247  // be able to put the app in the upper monitor)
248  int mbar_height, maxy, maxx;
249  GetMacDragWindowBounds(this, mbar_height, maxy, maxx);
250  wxPoint pos = this->GetPosition();
251  if (pos.y < mbar_height) {
252  pos.y = mbar_height;
253  this->SetPosition(pos);
254  }
255 #endif
256 
257  if (m_ShowPagerMessage && IsActive())
259 }
260 
261 void CWorkbenchFrame::OnActivate(wxActivateEvent& event)
262 {
264  event.Skip();
265 }
266 
267 namespace
268 {
269  class CPagerSlot : public wxPanel
270  {
271  DECLARE_EVENT_TABLE()
272  public:
273  CPagerSlot() {}
274  bool Create(CWorkbenchFrame *parent);
275 
276  void OnPaint(wxPaintEvent& event);
277  void OnMouseDown(wxMouseEvent& event);
278  void OnMouseEnter(wxMouseEvent& event);
279  void OnMouseLeave(wxMouseEvent& event);
280 
281  private:
282  CWorkbenchFrame* m_Frame = nullptr;
283  wxSizerItem* m_IconItem = nullptr;
284  wxIcon m_Icon;
285  bool m_Hot = false; // mouse inside
286  };
287 
288  BEGIN_EVENT_TABLE(CPagerSlot, wxPanel)
289  EVT_LEFT_DOWN(CPagerSlot::OnMouseDown)
290  EVT_ENTER_WINDOW(CPagerSlot::OnMouseEnter)
291  EVT_LEAVE_WINDOW(CPagerSlot::OnMouseLeave)
292  EVT_PAINT(CPagerSlot::OnPaint)
294 
295  bool CPagerSlot::Create(CWorkbenchFrame *parent)
296  {
297  m_Frame = parent;
298 
299  long style = wxBORDER_NONE;
300 
301  if (!wxPanel::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style))
302  return false;
303 
304  Hide();
305 
306  wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
307 
308  m_Icon = wxArtProvider::GetIcon(wxART_INFORMATION, wxART_OTHER, wxSize(16, 16));
309  m_IconItem = sizer->Add(16, 16, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 5);
310 
311  SetSizer(sizer);
312  Fit();
313 
314  return true;
315  }
316 
317  void CPagerSlot::OnPaint(wxPaintEvent& event)
318  {
319  wxPaintDC dc(this);
320 
321  if (m_Hot) {
322  wxBrush brush(CStatusBar::GetBackColor(true));
323  dc.SetBrush(brush);
324  dc.SetPen(*wxTRANSPARENT_PEN);
325  wxRect rc = GetClientRect();
326  dc.DrawRectangle(rc);
327  }
328 
329  wxRect rc = m_IconItem->GetRect();
330  dc.DrawIcon(m_Icon, rc.GetLeftTop());
331  }
332 
333  void CPagerSlot::OnMouseDown(wxMouseEvent& /*event*/)
334  {
335  m_Frame->SetShowPagerMessage();
336  }
337 
338  void CPagerSlot::OnMouseEnter(wxMouseEvent& event)
339  {
340  m_Hot = true;
341  Refresh();
342  }
343 
344  void CPagerSlot::OnMouseLeave(wxMouseEvent& event)
345  {
346  m_Hot = false;
347  Refresh();
348  }
349 }
350 
351 static const wxChar* kPagerFile = wxT("<home>/pager_message");
352 
353 void CWorkbenchFrame::SetPagerMessage(const string& message)
354 {
355  m_PagerMessage = message;
356  m_ShowPagerMessage = false;
357 
358  if (m_PagerMessage.empty())
359  return;
360 
361  IMenuService* menu_srv = m_Workbench->GetMenuService();
362  if (menu_srv)
363  menu_srv->ResetMenuBar();
364 
366  if (sb_srv) {
367  CPagerSlot* slot = new CPagerSlot();
368  if (slot->Create(this)) {
369 
370 #ifdef NCBI_OS_MSWIN // account for divider
371  int width = slot->GetSize().x;
372 #else // account for divider
373  int width = slot->GetSize().x + 5;
374 #endif
375  sb_srv->InsertSlot(1, slot, width);
376  slot->Show();
377  slot->SetToolTip(wxT("View Genome Workbench message"));
378  }
379  else
380  delete slot;
381  }
382 
383  m_ShowPagerMessage = true;
384 
385  wxString md5file = CSysPath::ResolvePath(kPagerFile);
386  if (::wxFileExists(md5file)) {
388  cs.AddLine(message);
389  string md5saved, md5 = cs.GetHexSum();
390 
391  try {
392  CNcbiIfstream ifs(md5file.fn_str());
393  ifs >> md5saved;
394  } NCBI_CATCH("Reading pager_message md5:");
395 
396  m_ShowPagerMessage = (md5 != md5saved);
397  }
398 }
399 
401 {
402  m_ShowPagerMessage = false;
403 
404  if (m_PagerMessage.empty())
405  return;
406 
409  string md5 = cs.GetHexSum();
410 
411  wxString md5file = CSysPath::ResolvePath(kPagerFile);
412 
413  bool doNotShowAgain = false;
414 
415  if (::wxFileExists(md5file)) {
416  string md5saved;
417 
418  try {
419  CNcbiIfstream ifs(md5file.fn_str());
420  ifs >> md5saved;
421  } NCBI_CATCH("Reading pager_message md5:");
422 
423  doNotShowAgain = (md5 == md5saved);
424  }
425 
426  CPagerMessageDlg dlg;
427  dlg.SetHTML(m_PagerMessage);
428  dlg.SetDoNotShow(doNotShowAgain);
429  dlg.Create(this);
430  dlg.ShowModal();
431  if (dlg.GetDoNotShow()) {
432  try {
433  CNcbiOfstream ofs(md5file.fn_str(), ios_base::out | ios_base::trunc);
434  ofs << md5;
435  } NCBI_CATCH("Writing pager_message md5:");
436  }
437  else
438  ::wxRemoveFile(md5file);
439 
440  if (dlg.GetOpenFeedback())
441  ShowFeedbackURL();
442 }
443 
Checksum and hash calculation classes.
CChecksum – Checksum calculator.
Definition: checksum.hpp:302
CDockManager CDockManager sends requests to Window Manager, Window Manager makes decisions about dele...
void OnKeyDown(wxKeyEvent &event)
void OnKeyUp(wxKeyEvent &event)
void RaiseFloatingInZOrder()
CMainFrame Base class for Application Main Frame, derive your frames from this one.
Definition: main_frame.hpp:52
void SetDoNotShow(bool value)
void SetHTML(wxString value)
bool GetOpenFeedback() const
bool GetDoNotShow() const
bool Create(wxWindow *parent, wxWindowID id=ID_CPAGERMESSAGEDLG, const wxString &caption=_("Genome Workbench Message"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(400, 300), long style=wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL)
Creation.
static wxColour GetBackColor(bool hot)
static wxString ResolvePath(const wxString &path, const wxString &rel_name)
Utility function to hide the platform specifics of locating our standard directories and files.
Definition: sys_path.cpp:106
CWorkbenchFrame Main Application Frame for Workbench-based applications.
IMenuService - Menu Service.
IWorkbench is the central interface in the application framework.
Definition: workbench.hpp:113
void(*)(CSeq_entry_Handle seh, IWorkbench *wb, const CSerialObject &obj) handler
std::ofstream out("events_result.xml")
main entry point for tests
void ShowFeedbackURL()
Open the feedback URL, using the default browser.
#define false
Definition: bool.h:36
#define bool
Definition: bool.h:34
static int trunc
Definition: array_out.c:8
static void md5(const char *src, const char *out)
Definition: challenge.c:77
#define NULL
Definition: ncbistd.hpp:225
string GetHexSum(void) const
Return string with checksum in hexadecimal form.
Definition: checksum.hpp:353
void AddLine(const char *line, size_t len)
Definition: checksum.hpp:609
#define _TRACE(message)
Definition: ncbidbg.hpp:122
#define NCBI_CATCH(message)
Catch CExceptions as well This macro is deprecated - use *_X or *_XX variant instead of it.
Definition: ncbiexpt.hpp:580
CDockManager * m_DockManager
virtual IMenuService * GetMenuService()=0
void SetPagerMessage(const string &message)
virtual bool CanShutDown()=0
void OnKeyUp(wxKeyEvent &event)
virtual void ForwardKeyEventsTo(CDockManager *manager)
IDockManagerKeyHook implementation.
virtual IStatusBarService * GetStatusBarService()=0
void OnActivate(wxActivateEvent &event)
void OnKeyDown(wxKeyEvent &event)
virtual void SetWorkbench(IWorkbench *workbench)
virtual void ShutDown()=0
CWorkbenchFrame()
Constructors.
virtual void ResetMenuBar()=0
bool ProcessEvent(wxEvent &event)
void OnCloseWindow(wxCloseEvent &event)
handle request to close window
IWorkbench * m_Workbench
void OnIdle(wxIdleEvent &event)
virtual void InsertSlot(int index, wxWindow *slot, int width=50)=0
void OnMove(wxMoveEvent &event)
@ eCmdParentMove
Definition: command.hpp:117
@ eCmdParentActivate
tool tip cmd indicating a main-window docking update
Definition: command.hpp:121
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ofstream CNcbiOfstream
Portable alias for ofstream.
Definition: ncbistre.hpp:500
IO_PREFIX::ifstream CNcbiIfstream
Portable alias for ifstream.
Definition: ncbistre.hpp:439
END_EVENT_TABLE()
#define wxT(x)
Definition: muParser.cpp:41
const struct ncbi::grid::netcache::search::fields::SIZE size
static Format format
Definition: njn_ioutil.cpp:53
wxEVT_COMMAND_MENU_SELECTED
static static static wxID_ANY
Definition: type.c:6
void SetFocus(CRef< objects::CSeq_entry > entry)
static const wxChar * kPagerFile
void GetMacDragWindowBounds(wxTopLevelWindow *win, int &menubar_height, int &maxy, int &maxx)
Returns window boundaries for mac (top menubar width and max height)
Definition: wx_utils.cpp:1239
void BroadcastCommandToChildWindows(wxWindow *window, int cmd_id, int cmd_data=0)
Sends command event with id 'cmd_id' to window and all its children.
Definition: wx_utils.cpp:1145
Modified on Wed May 15 15:03:08 2024 by modify_doxy.py rev. 669887