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

Go to the SVN repository for this file.

1 /* $Id: dock_manager.cpp 46600 2021-07-30 13:53:34Z asztalos $
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 
40 
44 
46 
49 
50 #include <wx/sizer.h>
51 #include <wx/settings.h>
52 #include <wx/utils.h>
53 #include <wx/menu.h>
54 
55 #ifdef __WXMAC__
56 #import <AppKit/NSWindow.h>
57 #endif
58 
61 
62 /// for debugging purpose
63 /*
64 static int s_CheckDragCount = 0;
65 
66 #define CHECK_DRAG {\
67  if( m_DragFrame ) { \
68  if( !m_DragFrame->IsActive() ){ \
69  ERR_POST( Error << "Drag frame lost its activation! [" << s_CheckDragCount++ << "]" ); \
70  }\
71  } else {\
72  ERR_POST( Error << "No drag frame! [" << s_CheckDragCount++ << "]" ); \
73  } \
74 }
75 #define RESET_CHECK_DRAG { s_CheckDragCount = 0; }
76 */
77 
78 ////////////////////////////////////////////////////////////////////////////////
79 /// CDockManager
80 
81 CDockManager::CDockManager(CWindowManager& manager, wxWindow& parent)
82 : m_ParentWindow(parent),
83  m_WindowManager(manager),
84  m_FrameHook(NULL),
85  m_MinContainer(NULL),
86  m_DragClient(NULL),
87  m_DragFrame(NULL),
88  m_ActiveDragContainer(NULL),
89  m_FocusedChild(0)
90 {
91  CDockContainer* container = new CDockContainer(*this, &parent, true);
92  m_Containers.push_back(container);
93 
94  m_MinContainer = new CMinPanelContainer(&parent, *this);
95  //WM_POST("CDockManager constructor m_Containers.push_back()" << this);
96 }
97 
98 
100 {
101  // delete all frames
102  TContainers conts = m_Containers; // make a copy to avoid side effects
103  for( size_t i = 0; i < conts.size(); i++ ) {
104  CDockContainer* cont = conts[i];
105  if(cont->GetDockFrame()) {
107  }
108  }
109 
110  _ASSERT(m_Containers.size() == 1);
111  m_Containers[0]->Destroy();
112  m_Containers.clear();
113 }
114 
115 
116 void CDockManager::SetKeyboardHook(wxFrame* frame)
117 {
118  m_FrameHook = dynamic_cast<IDockManagerKeyHook*>(frame);
119 }
120 
121 
123 {
124  return m_WindowManager;
125 }
126 
127 
129 {
130  return m_Containers.front();
131 }
132 
133 
135 {
136  return m_Containers.front();
137 }
138 
139 
141 {
142  return m_MinContainer;
143 }
144 
145 
146 // tries to find a saved position for the given window and place the window
147 // in the position. If no position found - adds window to the default container
149 {
150  CDockContainer* cont = NULL; // container that will host the client
151 
152  TFingerprint fingerprint = client.GetFingerprint();
153 
154  // check positions in visible containers
155  for( size_t i = 0; ! cont && i < m_Containers.size(); i++ ){
157  if( c->HasDefaultPositionFor(fingerprint) ){
158  cont = c;
159  }
160  }
161 
162  CFloatingFrame* frame = NULL;
163  if( ! cont ){
164  // check positions in hidden floating frames
167  CDockContainerDescr& descr = **it;
168  CDockLayoutTree& tree = *descr.GetTree();
169 
170  // FIXME: this fixes situation, which should not happen, but still happens
171  // somehow during complex layout operations and leads to crash
172  // ALL clients should be HIDDEN in hidden floating frame
173  tree.HideAll();
174 
175  if(tree.FindByFingerprint(fingerprint)) {
176  frame = x_CreateFrameAndContainer(descr.GetPos(), descr.GetSize(), &tree);
177  cont = frame->GetDockContainer();
178  descrs.erase(it);
179  break;
180  }
181  }
182  }
183  if( ! cont) {
184  if (bFloat) {
185  wxRect panel_rc = GetScreenRect(m_ParentWindow);
186  wxPoint pos = panel_rc.GetLeftTop();
187  pos += wxPoint(40, 40);
188  frame = x_CreateFrameAndContainer(pos, panel_rc.GetSize(), NULL);
189  cont = frame->GetDockContainer();
190  }
191  else
192  cont = GetMainContainer();
193  }
195 
196  if(frame) {
197  frame->Show();
198  frame->SetFocus();
199  }
200  client.GetWindow()->SetFocus();
201 }
202 
203 
205 {
206  CDockPanel* panel = x_GetDockPanel(client);
207  _ASSERT(panel);
208 
209  if(panel) {
210  Remove(*panel);
211  }
212 }
213 
214 
215 // removes IDockableWindow (IWMCLient in Dock Panel or Dock Container)
216 // from Dock Manager and destroys its window, does not send any
217 // notifications to Window Manager
219 {
220  CDockContainer* cont = dockable.GetDockContainer();
221  if(cont) {
222  cont->RemoveWindow(dockable, CDockContainer::eDestroyWin); // destroy client
223 
224  if(GetMainContainer() != cont && cont->HasNoWMClients()) {
226  }
227  } else {
228  // this is a minimized window or a logical error
229  CDockPanel* panel = dynamic_cast<CDockPanel*>(&dockable);
230  _ASSERT(m_MinContainer->HasClient(*panel));
231 
232  if(m_MinContainer) {
233  m_MinContainer->RemoveClient(*panel);
235  panel->Destroy();
236  }
237  }
238 }
239 
240 
241 /// moves the given client into the Main Tab Control ("Reset")
243 {
245  CDockContainer* cont = dockable->GetDockContainer();
246 
247  if(cont) {
248  // the client is in container
249  CRef<TNode> full_node = cont->RemoveWindow(*dockable, CDockContainer::eMoveWin);
250 
251  if(GetMainContainer() != cont && cont->HasNoWMClients()) {
253  }
255  } else {
256  // this is a minimized window
257  CDockPanel* panel = dynamic_cast<CDockPanel*>(dockable);
258  _ASSERT(m_MinContainer->HasClient(*panel));
259 
260  if(m_MinContainer) {
261  m_MinContainer->RemoveClient(*panel);
262  }
263 
264  CRef<TNode> full_node(new TNode(CDockLayoutTree::eClient, panel));
265  full_node->Link(*new TNode(*full_node));
266 
267  TFingerprint p = client.GetFingerprint();
268  full_node->SetFingerprint(p);
269  full_node->GetClone()->SetFingerprint(p);
270 
272  }
273 }
274 
275 
277 {
278  CDockPanel* panel = x_GetDockPanel(client);
279  _ASSERT(panel);
280 
281  if (IsFloating(client))
282  return panel->GetDockContainer()->GetDockFrame();
283 
284  wxFrame* frame = x_MoveToFloatingFrame(*panel, true);
285 
286  if (m_FocusedChild) {
287  m_FocusedChild->SetFocus();
288  m_FocusedChild = 0;
289  }
290 
291  return frame;
292 }
293 
294 
296 {
297  CDockPanel* panel = x_GetDockPanel(client);
298 
299  CDockContainer* cont = panel->GetDockContainer();
301 
302  m_MinContainer->AddClient(*panel);
303 
304  if(GetMainContainer() != cont && cont->HasNoWMClients()) {
306  }
307 }
308 
309 
311 {
312  CDockPanel* panel = x_GetDockPanel(client);
313 
314  if( panel ){
315  m_MinContainer->RemoveClient( *panel );
316  }
317 
318  AddToDefaultLocation( client, false );
319 }
320 
321 
323 {
324  CDockPanel* panel = x_GetDockPanel(client);
325 
326  _ASSERT(panel);
327 
328  CDockContainer* cont = panel->GetDockContainer();
329  return cont == GetMainContainer();
330 }
331 
332 
334 {
335  CDockPanel* panel = x_GetDockPanel(client);
336 
337  _ASSERT(panel);
338 
339  CDockContainer* cont = panel->GetDockContainer();
340  return cont && cont->IsRootWindow(panel);
341 }
342 
343 
345 {
346  CDockPanel* panel = x_GetDockPanel(client);
347  return panel ? m_MinContainer->HasClient(*panel) : false;
348 }
349 
350 
352 {
353  wxWindow* window = client.GetWindow();
354  for (;window;) {
355  wxWindow* parent = window->GetParent();
356  CDockPanel* panel = dynamic_cast<CDockPanel*>(parent);
357  if (panel)
358  return panel;
359  window = parent;
360  }
361  return 0;
362 }
363 
364 
365 // Make clients visible and moves focus to the first client in the list.
367 {
368  // first restore clients if needed
369  NON_CONST_ITERATE(TClients, it, clients) {
370  IWMClient& the_client = **it;
371  if(IsMinimized(the_client)) {
372  Restore(the_client);
373  }
374  }
375 
376  // iterate by Dock Container, activate clients in each container
377  for( size_t i = 0; i < m_Containers.size(); i++ ) {
378  CDockContainer* cont = m_Containers[i];
379  cont->ActivateClients(clients);
380  }
381  // focus the first one
382  if(clients.size()) {
383  IWMClient* client = *clients.begin();
384  client->GetWindow()->SetFocus();
385 
386  #ifdef _DEBUG
387  wxRect winloc = client->GetWindow()->GetRect();
388  wxPoint scrpnt = client->GetWindow()->GetScreenPosition();
389  ERR_POST(
390  Info << "Client location is "
391  "(" << winloc.x << "/" << scrpnt.x << ", " << winloc.y << "/" << scrpnt.y << ")"
392  "[" << winloc.width << ", " << winloc.height << "]"
393  );
394  #endif
395  }
396 }
397 
398  void CDockManager::OnMove(wxMoveEvent& event)
399  {
400  // iterate by Dock Container, sending a move event to each one
401  // so that it can in turn move attached client frames (sticky tool tips).
402  for( size_t i = 0; i < m_Containers.size(); i++ ) {
403  CDockContainer* cont = m_Containers[i];
405  }
406  }
407 
408 
410 {
411  wxWindow* w = &m_ParentWindow;
412  for( ;w->GetParent(); w = w->GetParent()) {
413  }
414  return w;
415 }
416 
417 void CDockManager::OnBeginDrag(IDockableWindow& dockable, const wxPoint& sc_mouse_pos)
418 {
419  //WM_POST("CDockManager::OnBeginDrag()");
420 
421  if( m_DragClient ){
422  return; // already dragging
423  }
424 
425  m_DragClient = &dockable;
426  m_DragFrame = dynamic_cast<CFloatingFrame*>(&dockable);
427  m_PrevDragPos = sc_mouse_pos;
428 
429  m_FocusedChild = 0;
430 
431  // if (m_DragFrame) - we move the whole frame
432  if( !m_DragFrame ){
433  wxWindow* window = dynamic_cast<wxWindow*>(&dockable);
434 
435  CDockContainer* cont = dockable.GetDockContainer();
436  if(cont->IsRootWindow(window)) {
437  // dockable is the Root Window for this container, so we do not need to create
438  // a special Floating Frame - we will use the Frame that hosts this Dock Container
439  m_DragFrame = cont->GetDockFrame();
440  }
441  if( ! m_DragFrame) {
442  // create a new Floating Frame to host dockable
443  m_DragFrame = x_MoveToFloatingFrame(dockable, false);
444  }
445  }
446 
447  m_DragFrame->SetFocus();
448 
450 
451  // now start handling dragging events
452  OnDrag( dockable, sc_mouse_pos );
453 
454  if(m_FrameHook) {
456  }
457 
458  //WM_POST("CDockManager::OnBeginDrag END");
459 }
460 
461 
462 bool CDockManager::OnDrag(IDockableWindow& dockable, const wxPoint& sc_mouse_pos)
463 {
464  //WM_POST("CDockManager::OnDrag()");
465 
466  if(m_DragFrame) {
467  _ASSERT(&dockable == m_DragClient);
468 
469  // find the container that handles the dragging
470  CDockContainer* active_cont = x_GetActiveContainerByPos(sc_mouse_pos);
471 
472  if(active_cont != m_ActiveDragContainer) {
473  // new active container - deactivate the old container and initiate the new one
474 
475  // stop dragging in the currently active container
477  wxWindow* dummy = NULL;
479  }
480 
481  m_ActiveDragContainer = active_cont;
482 
483  // activate new container
485  m_ActiveDragContainer->OnBeginDragOver(sc_mouse_pos);
486  }
487  } else {
488  // active container is the same - forward the event to the container
490  m_ActiveDragContainer->OnDragOver(sc_mouse_pos);
491  }
492  }
493 
494  if(m_DragClient != m_DragFrame) {
495  // move frame only if it is not being moved by the system
496  x_MoveDragFrame(sc_mouse_pos);
497  }
498  return true;
499  }
500  return false;
501  //WM_POST("CDockManager::OnDrag() END");
502 }
503 
504 
505 
506 // handles the ending of a D&D docking session
507 // if result == eCancel we simply end the session, but do not
508 // change window layout
510  const wxPoint& sc_mouse_pos)
511 {
512  //WM_POST("CDockManager::OnEndDrag() result " << result);
513 
514  if( m_DragFrame ){
515  // handle the last mouse movement
516  OnDrag( dockable, sc_mouse_pos );
517 
518  if( m_FrameHook ){
520  }
521 
522  if (m_FocusedChild)
523  m_FocusedChild->SetFocus();
524  else
525  m_DragFrame->SetFocus();
526 
527  if( m_ActiveDragContainer ){
528  wxWindow* target = NULL;
530 
531  //m_DragFrame->Refresh();
532 
533  if(/*(result != eCancel) &&*/ effect != eNoEffect) {
534  // handle Drop
536 
538 
539  IDockableWindow* dock_client = &dockable;
540  if(m_DragClient == m_DragFrame) {
541  // we drag a frame, get the root window from the frame
542  dock_client = dynamic_cast<IDockableWindow*>(cont->GetRootWindow());
543  } else {
544  // we drag a child of a frame, cast the child
545  dock_client = &dockable;
546  }
547 
548 
549  // Let subwindows know window is about to be docked
550  wxWindow* window = dynamic_cast<wxWindow*>(dock_client);
552 
553  CRef<TNode> full_node = cont->RemoveWindow(*dock_client, CDockContainer::eMoveWin);
554 
555  // add the client to the new Dock Container
556  m_ActiveDragContainer->AddClient(full_node, effect, target);
557 
558  if(cont->HasNoWMClients()) {
559  // prevent main window activation
560  CFloatingFrame* frame = cont->GetDockFrame();
561  frame->SetWindowStyleFlag(frame->GetWindowStyleFlag()&~wxFRAME_FLOAT_ON_PARENT);
562  x_DestroyFrameAndContainer(cont); // we do not need this container anymore
563  }
564 
565  if (m_FocusedChild)
566  m_FocusedChild->SetFocus();
567  else
568  full_node->GetWindow()->SetFocus();
569 
570  // Parent of target will enclose the dropped window (target itself
571  // does not always enclose dropped window).
572  wxWindow* w = target;
573  if (target->GetParent() != NULL)
574  w = target->GetParent();
575 
576  bool is_main_window = false;
577 
578  wxWindow* p = w;
579  CFloatingFrame* ff = NULL;
580  while (p != NULL && ff == NULL) {
581  ff = dynamic_cast<CFloatingFrame*>(p);
582  p = p->GetParent();
583  }
584  if (ff!=NULL)
585  is_main_window = false;
586  else
587  is_main_window = true;
588 
589  if (is_main_window) {
590  // Let all subwindows know dock has been completed. This is only needed due
591  // to problems with tooltip windows on mac (tooltips in main window can
592  // disappear after a docking event)
593  static int drop_count = 0;
594  ++drop_count;
597  }
598  else {
599  // Let subwindows know dock has been completed
601  }
602  }
603  }
604 
605  m_DragClient = NULL;
606  m_DragFrame = NULL;
608  m_FocusedChild = 0;
609  }
610 
611  //WM_POST("CDockManager::OnEndDrag() END");
612 }
613 
614 
616 {
617  //WM_POST("CDockManager::OnCancelDrag()");
618  OnEndDrag(*m_DragClient, eCancel, ::wxGetMousePosition());
619 }
620 
621 
622 /// Creates a new top-level Floating Frame and a Dock Container that will be
623 /// hosted in the frame.
626  const wxSize& size,
628 {
629  // create a Frame
630  CFloatingFrame* frame = new CFloatingFrame(*this, GetTopAppWindow(), pos, size);
631  string title = m_WindowManager.GetNewFloatingFrameTitle();
632  frame->SetTitle(ToWxString(title));
633 
634  // create a Dock Container
635  CDockContainer* frame_cont = new CDockContainer(*this, frame, false);
636  if(tree) {
637  frame_cont->SetFullTree(*tree);
638  }
639  m_Containers.push_back(frame_cont);
640 
641  // bind Container to the Frame
642  frame->SetDockContainer(frame_cont);
643  frame_cont->Reparent(frame);
644 
645  return frame;
646 }
647 
648 
649 /// Destroys a Docking Container togather with its Floating Frame.
651 {
652  bool can_do = cont && cont->HasNoWMClients();
653  _ASSERT(can_do);
654 
655  if(can_do) {
656  CFloatingFrame* frame = cont->GetDockFrame();
657 
658  // save layout of this Dock Container if needed
659  if(cont->NeedToSavePositions()) {
661  new CDockContainerDescr(frame->GetPosition(), frame->GetSize(), frame->IsMaximized(),
662  cont->DisconnectTrees()));
663  m_DeadFrameDescrs.AddItem(descr);
664  }
665  // remove this Dock Container from m_Containers
666  TContainers::iterator it = find(m_Containers.begin(), m_Containers.end(), cont);
667  m_Containers.erase(it);
668 
669  // Destroy the Frame (together with the Container)
670  //WM_POST(" Destroy the Frame (together with the Container) " << frame);
671  frame->Destroy();
672  }
673 }
674 
675 
676 // Moves IDockableWindow that is already managed by the Dock Manager into a
677 // separate floating frame
680 {
681  wxWindow* window = dynamic_cast<wxWindow*>(&dockable);
682 
683  m_FocusedChild = 0;
684  wxWindow* focused = wxWindow::FindFocus();
685  wxWindow* w = focused;
686  while (w) {
687  if (w == window) {
688  m_FocusedChild = focused;
689  break;
690  }
691  if (w->IsTopLevel())
692  break;
693  w = w->GetParent();
694  }
695 
696  CDockContainer* cont = dockable.GetDockContainer();
697  wxPoint sc_origin = window->GetScreenPosition();
698 
699  //This warns subwindows that the window will be docked
701 
702  // create Frame and Dock Container and bind them together
703  wxRect panel_rc = GetScreenRect(*window);
704  CDockPanel* panel = dynamic_cast<CDockPanel*>(&dockable);
705  wxPoint pos = panel_rc.GetLeftTop();
706  if(shift) {
707  pos += wxPoint(40, 40);
708  }
709  wxSize size = panel_rc.GetSize();
710 
712  CDockContainer* frame_cont = frame->GetDockContainer();
713 
714  IWMClient* wmClient = panel->GetClient();
715 
716  if(cont) {
717  // the client is in container
718  // remove the client from its current container, but do not destroy it
719  CRef<TNode> full_node = cont->RemoveWindow(dockable, CDockContainer::eMoveWin);
720 
721  // add the client to the new container
722  frame_cont->AddClientToCentralPane(full_node);
723  } else {
724  // this is a minimized window
725  _ASSERT(m_MinContainer->HasClient(*panel));
726 
727  if(m_MinContainer) {
728  m_MinContainer->RemoveClient(*panel);
729  }
730 
731  CRef<TNode> full_node(new TNode(CDockLayoutTree::eClient, panel));
732  full_node->Link(*new TNode(*full_node));
733 
734  TFingerprint p = wmClient->GetFingerprint();
735  full_node->SetFingerprint(p);
736  full_node->GetClone()->SetFingerprint(p);
737 
738  frame_cont->AddClientToCentralPane(full_node);
739  }
740 
741 
742 #ifndef __WXGTK__
743  // adjust position so that dockable stays in the same place on screen
744  wxPoint sc_new_origin = window->GetScreenPosition();
745  wxPoint frame_pos = frame->GetScreenPosition();
746 
747  wxPoint delta = sc_origin - sc_new_origin;
748  frame_pos += delta;
749  frame->Move(frame_pos);
750 #endif
751 
752  window->Show();
753  frame->Show();
754  frame->SetFocus();
755 
756  //Tell subwindows that the dock has been completed
758 
759  if (wmClient->IsAForm()) {
760  size = wmClient->GetWindow()->GetVirtualSize();
761  size = panel->ClientToWindowSize(size);
762  size = frame->ClientToWindowSize(size);
763  frame->SetSize(size);
764  }
765 
766  return frame;
767 }
768 
769 
770 void CDockManager::x_MoveDragFrame(const wxPoint& sc_mouse_pos)
771 {
772  if(sc_mouse_pos != m_PrevDragPos) {
773  wxPoint delta = sc_mouse_pos - m_PrevDragPos;
774 
775  //WM_POST("CDockManager::x_MoveDragDrame() m_PrevDragPos.y " << m_PrevDragPos.y << ", sc_mouse_pos.y " << sc_mouse_pos.y);
776 
777  wxPoint pos = m_DragFrame->GetPosition();
778 
779 #ifdef __WXMAC__
780  int maxy = 4096;
781  int maxx;
782  int menubar_height;
783 
784  GetMacDragWindowBounds(m_DragFrame, menubar_height, maxy, maxx);
785 
786  // Do not move the window if the mouse is in the system menubar area
787  if (!(//sc_mouse_pos.y < m_DragFrame->GetRect().GetTop() ||
788  sc_mouse_pos.y < menubar_height)) {
789  if (pos.y + delta.y > menubar_height && pos.y + delta.y < maxy) {
790  //_TRACE("New Position: (" << pos.x << ", " << pos.y << ")");
791  pos += delta;
792  m_DragFrame->SetPosition(pos);
793 
794  m_PrevDragPos = sc_mouse_pos;
795  }
796  else {
797  //_TRACE("Update rejected. Height = " << menubar_height);
798  pos += delta;
799  if (pos.y < menubar_height)
800  pos.y = menubar_height;
801  if (pos.y > maxy)
802  pos.y = maxy;
803  m_DragFrame->SetPosition(pos);
804 
805  m_PrevDragPos = sc_mouse_pos;
806  }
807  }
808 #else
809  pos += delta;
810  m_DragFrame->SetPosition(pos);
811 
812  m_PrevDragPos = sc_mouse_pos;
813 #endif
814 
815  } //else WM_POST("CDockManager::x_MoveDragDrame - skipping");
816 }
817 
818 
820 {
821  CDockContainer* dragged_cont = m_DragFrame->GetDockContainer();
822 
823  for(int i = (int)m_Containers.size()-1; i >= 0; i-- ) {
824  CDockContainer* cont = m_Containers[i];
825 
826  if(cont != dragged_cont) {
827  wxRect rc = GetScreenRect(*cont);
828 
829  if(rc.Contains(sc_mouse_pos)) {
830  return cont;
831  }
832  }
833  }
834  return NULL;
835 }
836 
837 
838 void CDockManager::OnFloatingPaneBeginMove(CFloatingFrame& frame, const wxPoint& sc_mouse_pos)
839 {
840  //WM_POST("CDockManager::OnFloatingPaneBeginMove()");
841 
842  if(m_DragClient == NULL) {
843  OnBeginDrag(frame, sc_mouse_pos);
844  }
845 }
846 
847 
848 void CDockManager::OnFloatingPaneMoving(CFloatingFrame& frame, const wxPoint& sc_mouse_pos)
849 {
850  //WM_POST("CDockManager::OnFloatingPaneMoving()");
851  if(m_DragClient == &frame) {
852  OnDrag(frame, sc_mouse_pos);
853  }
854 }
855 
856 
858 {
859  WM_POST("CDockManager::OnFloatingPaneEndMove");
860  if(m_DragClient == &frame) {
861  OnEndDrag(frame, result, sc_mouse_pos);
862  }
863 }
864 
865 
867 {
869  IWMClient* client = panel.GetClient();
870 
871  wxMenu* menu = new wxMenu();
872 
873  if(IsMinimized(*client)) {
874  cmd_reg.AppendMenuItem(*menu, eCmdWindowRestore);
875  } else {
876  cmd_reg.AppendMenuItem(*menu, eCmdWindowMinimize);
877  }
878  if( ! IsFloating(*client)) {
879  cmd_reg.AppendMenuItem(*menu, eCmdWindowFloat);
880  }
881  if( ! IsInMainTab(*client)) {
882  cmd_reg.AppendMenuItem(*menu, eCmdMoveToMainTab);
883  }
884  if(client && client->GetColor()) {
885  cmd_reg.AppendMenuItem(*menu, eCmdSetClientColor);
886  }
887 
888  return menu;
889 }
890 
891 
893 {
895 }
896 
897 
898 void CDockManager::OnKeyDown(wxKeyEvent& event)
899 {
900  //WM_POST("CDockManager::OnKeyDown");
901 
902  int code = event.GetKeyCode();
903  if(code == WXK_ESCAPE) {
904  OnCancelDrag();
905  } else if(code == WXK_SHIFT && m_ActiveDragContainer) {
906  wxPoint sc_mouse = wxGetMousePosition();
908  } else {
909  event.Skip();
910  }
911 }
912 
913 
914 void CDockManager::OnKeyUp(wxKeyEvent& event)
915 {
916  //WM_POST("CDockManager::OnKeyUp");
917 
918  int code = event.GetKeyCode();
919  if(code == WXK_SHIFT && m_ActiveDragContainer) {
920  wxPoint sc_mouse = wxGetMousePosition();
922  } else {
923  event.Skip();
924  }
925 }
926 
927 
929 {
930  CDockPanel* panel = dynamic_cast<CDockPanel*>(&dockable);
931  _ASSERT(panel);
932 
934 }
935 
936 
937 // a handler for frame's close button
939 {
940  //WM_POST("CDockManager::OnCloseFrame()");
941 
942  frame->Hide(); // do not close it yet
943 
944  CDockContainer* cont = frame->GetDockContainer();
945 
946  vector<IWMClient*> clients;
947  cont->GetAllClients(clients);
948 
949  // place a request to close all clients in the frame
950  // when it happens, the frame will be closed automatically
952 }
953 
954 
955 void CDockManager::OnTabClosePressed(const vector<IWMClient*>& clients)
956 {
957  //WM_POST("CDockManager::OnTabClosePressed()");
959 }
960 
962 {
963  // Order m_Containers may be updated during the Raise() command
964  // via an activate event that calls OnFloatingFrameActivateEvent,
965  // so make a copy of the container first.
966  TContainers cont_copy = m_Containers;
967  TContainers::iterator it;
968 
969  for (it=cont_copy.begin(); it!=cont_copy.end(); ++it) {
970  wxWindow* w = *it;
971  CFloatingFrame* f = NULL;
972 
973  while (w!=NULL && f==NULL) {
974  f = dynamic_cast<CFloatingFrame*>(w);
975  if (f!=NULL) {
976  f->Raise();
977  }
978  w = w->GetParent();
979  }
980  }
981 }
982 
984 {
985  // See if any windows overlap "r" and if so call RaiseFloatingInZOrder
986  TContainers::iterator it;
987  bool overlap = false;
988 
989  for (it=m_Containers.begin(); it!=m_Containers.end() && !overlap; ++it) {
990  wxWindow* w = *it;
991  CFloatingFrame* f = NULL;
992 
993  while (w!=NULL && f==NULL) {
994  f = dynamic_cast<CFloatingFrame*>(w);
995  w = w->GetParent();
996  }
997  if (f!=NULL) {
998  if (f->GetRect().Intersects(r))
999  overlap = true;
1000  }
1001  }
1002 
1003  if (overlap)
1005 
1006 }
1007 
1009 {
1010  _ASSERT(frame);
1011 
1012  if(frame && active) {
1013  // frame is activate - bring it to the top in Z-order
1014  CDockContainer* cont = frame->GetDockContainer();
1015  _ASSERT(cont);
1016 
1017  //WM_POST(" CDockManager::OnFloatingFrameActivateEvent() cont " << cont);
1018 
1019  TContainers::iterator it =
1020  std::find(m_Containers.begin(), m_Containers.end(), cont);
1021 
1022 #ifndef __WXGTK__
1023  _ASSERT(it != m_Containers.end());
1024 #endif
1025  if (it != m_Containers.end()) {
1026  m_Containers.erase(it);
1027  m_Containers.push_back(cont);
1028  }
1029  }
1030 }
1031 
1032 
1033 ///////////////////////////////////////////////////////////////////////////////
1034 /// Saving and Loading layouts
1035 
1036 static const char* kContainersTag = "Containers";
1037 static const char* kLayoutTag2 = "Dock Manager Layout 2";
1038 static const char* kVideoIdTag = "VideoId";
1039 
1040 const int kMaxContainers = 10;
1041 
1043 {
1044  CRef<CUser_object> layout(new CUser_object());
1045  layout->SetType().SetStr(kLayoutTag2);
1046 
1047  wxFrame* mainFrame = m_WindowManager.GetMainWindow();
1048 
1049  vector<CRef<CUser_object> > descrs;
1050 
1051  for (size_t i = 0; i < m_Containers.size(); i++) {
1052  CDockContainer* cont = m_Containers[i];
1053  CRef<CUser_object> contDesc(cont->SaveLayout(mainFrame));
1054  if (contDesc)
1055  descrs.push_back(contDesc);
1056  else if (i == 0) {
1057  _ASSERT(false);
1058  return 0;
1059  }
1060  }
1061 
1063  if (descrs.size() >= kMaxContainers)
1064  break;
1065 
1066  CRef<CUser_object> contDesc((*it)->ToUserObject());
1067  if (contDesc) descrs.push_back(contDesc);
1068  }
1069 
1070  layout->AddField(kVideoIdTag, GetVideoId());
1071  layout->AddField(kContainersTag, descrs);
1072 
1073  return layout.Release();
1074 }
1075 
1076 bool CDockManager::x_ReadLayout(const objects::CUser_object& object, vector<CRef<CDockContainerDescr> >& descriptors, string& videoId)
1077 {
1078  if (!object.GetType().IsStr() || object.GetType().GetStr() != kLayoutTag2) {
1079  LOG_POST(Error << "Invalid layout object");
1080  return false;
1081  }
1082 
1083  bool result = false;
1084  try {
1085  videoId = object.GetField(kVideoIdTag).GetData().GetStr();
1086  const vector<CRef<CUser_object> >& descrs =
1087  object.GetField(kContainersTag).GetData().GetObjects();
1088  for (size_t i = 0; i < descrs.size(); ++i) {
1089  descriptors.push_back(CRef<CDockContainerDescr>(CDockContainerDescr::FromUserObject(*descrs[i])));
1090  }
1091  result = true;
1092  } NCBI_CATCH("CDockManager::x_ReadLayout()");
1093 
1094  return result;
1095 }
1096 
1098 {
1099  vector<CRef<CDockContainerDescr> > descrs;
1100  string videoId;
1101 
1102  if (!x_ReadLayout(object, descrs, videoId))
1103  return;
1104 
1105  if (descrs.empty()) {
1106  LOG_POST(Error << "Failed to read layout: " << "Empty layout");
1107  return;
1108  }
1109 
1110  vector<IWMClient*> allClients;
1111  for( size_t i = 0; i < m_Containers.size(); i++) {
1112  CDockContainer* cont = m_Containers[i];
1113 
1114  vector<IWMClient*> clients;
1115  cont->GetAllClients(clients);
1116  allClients.insert(allClients.end(), clients.begin(), clients.end());
1117 
1118  ITERATE(vector<IWMClient*>, it, clients)
1119  Minimize(**it);
1120  }
1121 
1122  m_DeadFrameDescrs.SetItems().clear();
1123 
1124  CRef<CDockContainerDescr> mainDescr = descrs[0];
1125  descrs.erase(descrs.begin());
1126 
1127  wxFrame* mainFrame = m_WindowManager.GetMainWindow();
1128  if (videoId == GetVideoId()) {
1129  mainFrame->SetSize(mainDescr->GetRect());
1130  } else {
1131  LOG_POST(Info << "Applying layout: VideoId mismatch");
1132  }
1133  if (mainDescr->GetMaximized() && !mainFrame->IsMaximized())
1134  mainFrame->Maximize();
1135  GetMainContainer()->ApplyLayout(*mainDescr->GetTree());
1136 
1137  REVERSE_ITERATE(vector<CRef<CDockContainerDescr> >, it, descrs)
1139 
1140  ITERATE(vector<IWMClient*>, it, allClients)
1141  Restore(**it);
1142 }
1143 
1145 {
1146 public:
1147  FClientFinder(set<string>& views) : m_Views(views) {}
1148 
1150  {
1151  if (!node.IsContainer() && node.IsVisible()) {
1152  IWMClient::CFingerprint fingerprint = node.GetFingerprint();
1153  if (!fingerprint.IsEmpty()) {
1154  m_Views.insert(fingerprint.GetId());
1155  }
1156  }
1157  }
1158 
1159 protected:
1161 };
1162 
1163 
1165 {
1166  vector<CRef<CDockContainerDescr> > descrs;
1167  string videoId;
1168 
1169  if (!x_ReadLayout(object, descrs, videoId))
1170  return;
1171 
1172  if (descrs.empty()) {
1173  LOG_POST(Error << "Failed to read layout: " << "Empty layout");
1174  return;
1175  }
1176 
1177  set<string> viewsToCreate;
1178  NON_CONST_ITERATE(vector<CRef<CDockContainerDescr> >, it, descrs) {
1179  FClientFinder finder(viewsToCreate);
1180  (*it)->GetTree()->DepthFirstForEach(finder);
1181  }
1182 
1183  m_DeadFrameDescrs.SetItems().clear();
1184 
1185  CRef<CDockContainerDescr> mainDescr = descrs[0];
1186  descrs.erase(descrs.begin());
1187 
1188  wxFrame* mainFrame = m_WindowManager.GetMainWindow();
1189  GetMainContainer()->ApplyLayout(*mainDescr->GetTree());
1190 
1191  REVERSE_ITERATE(vector<CRef<CDockContainerDescr> >, it, descrs)
1193 
1194  ITERATE(set<string>, it, viewsToCreate) {
1195  IWMClient::CFingerprint fingerprint(*it, true);
1196  IWMClient* client = factory.CreateClient(fingerprint, mainFrame);
1197  if (!client) continue;
1198  m_WindowManager.AddClient(*client, false);
1199  }
1200 }
1201 
1202 
static CBioSource dummy
static CDockContainerDescr * FromUserObject(const objects::CUser_object &obj)
wxSize GetSize() const
wxPoint GetPos() const
CDockLayoutTree * GetTree()
CDockContainer is a window that hosts docked windows.
bool HasDefaultPositionFor(const TFingerprint &fingerprint)
void OnBeginDragOver(const wxPoint &sc_mouse_pt)
bool IsRootWindow(wxWindow *window)
EDockEffect OnEndDragOver(wxWindow *&target)
CRef< TNode > RemoveWindow(IDockableWindow &dockable, ERemoveAction action)
CFloatingFrame * GetDockFrame()
returns floating frame hosting this container
void ApplyLayout(CDockLayoutTree &tree)
bool NeedToSavePositions()
void AddClientToDefaultLocation(IWMClient &client)
wxWindow * GetRootWindow()
returns window representing the root of the layout hosted by the container
void GetAllClients(vector< IWMClient * > &clients)
void SetFullTree(CDockLayoutTree &full_tree)
initialize the container with the layout tree
void OnDragOver(const wxPoint &sc_mouse_pt)
objects::CUser_object * SaveLayout(wxFrame *mainFrame)
void AddClient(CRef< TNode > full_client, EDockEffect effect, wxWindow *target_w)
void AddClientToCentralPane(CRef< TNode > full_client)
CRef< CDockLayoutTree > DisconnectTrees()
void ActivateClients(vector< IWMClient * > &clients)
bool HasNoWMClients()
returns true if Dock Container does not have any IWMClients as children
CNode - a node in layout tree corresponding to a window.
Definition: dock_layout.hpp:77
bool IsVisible() const
Definition: dock_layout.hpp:99
bool IsContainer() const
Definition: dock_layout.hpp:93
TFingerprint GetFingerprint() const
CDockLayoutTree - represents hierarchical layout in a Dock Container as a tree where nodes correspond...
Definition: dock_layout.hpp:64
void x_MoveDragFrame(const wxPoint &sc_mouse_pos)
objects::CUser_object * SaveLayout()
produces Memento describing the current window layout (including all clients)
void OnFloatingPaneBeginMove(CFloatingFrame &frame, const wxPoint &sc_mouse_pos)
void Restore(IWMClient &client)
TDescrMRUList m_DeadFrameDescrs
void MoveToMainTab(IWMClient &client)
moves the given client into the Main Tab Control ("Reset")
void OnKeyDown(wxKeyEvent &event)
vector< IWMClient * > TClients
CDockLayoutTree::CNode TNode
void OnKeyUp(wxKeyEvent &event)
wxWindow * GetTopAppWindow()
CDockContainer * m_ActiveDragContainer
bool OnDockPanelCommand(CDockPanel &panel, TCmdID cmd)
CWindowManager & GetWindowManager()
void OnBeginDrag(IDockableWindow &dockable, const wxPoint &sc_mouse_pos)
void OnFloatingFrameActivateEvent(CFloatingFrame *frame, bool active)
void OnFrameClosePressed(CFloatingFrame *frame)
CWindowManager & m_WindowManager
void x_DestroyFrameAndContainer(CDockContainer *cont)
Destroys a Docking Container togather with its Floating Frame.
bool x_ReadLayout(const objects::CUser_object &object, vector< CRef< CDockContainerDescr > > &descriptors, string &videoId)
IDockManagerKeyHook * m_FrameHook
wxFrame * MoveToFloatingFrame(IWMClient &client)
wxMenu * GetDockPanelMenu(CDockPanel &panel)
CFloatingFrame * x_CreateFrameAndContainer(const wxPoint &pos, const wxSize &size, CDockLayoutTree *tree)
Creates a new top-level Floating Frame and a Dock Container that will be hosted in the frame.
void AddToDefaultLocation(IWMClient &client, bool bFloat)
vector< CDockContainer * > TContainers
CDockContainer * GetMainContainer()
CMinPanelContainer * GetMinPanelContainer()
static CDockPanel * x_GetDockPanel(IWMClient &client)
bool OnDrag(IDockableWindow &dockable, const wxPoint &sc_mouse_pos)
void Remove(IWMClient &client)
void OnTabClosePressed(const vector< IWMClient * > &clients)
void OnCancelDrag()
void LoadLayout(const objects::CUser_object &object, IWMClientFactory &factory)
creates a new window layout based on the given Memento instantiates the clients as needed using the g...
CFloatingFrame * m_DragFrame
CDockContainer * x_GetActiveContainerByPos(const wxPoint &sc_mouse_pos)
IDockableWindow * m_DragClient
TContainers m_Containers
A list of all Dock containers, the first container in the list is the main one.
CMinPanelContainer * m_MinContainer
holds minimized IWMClients
void ActivateClients(TClients &clients)
void OnEndDrag(IDockableWindow &dockable, EDragResult result, const wxPoint &sc_mouse_pos)
void OnCloseDockable(IDockableWindow &dockable)
wxWindow * m_FocusedChild
wxWindow & m_ParentWindow
a window that hosts the main dock container
bool IsInMainTab(IWMClient &client) const
CDockManager(CWindowManager &manager, wxWindow &parent)
for debugging purpose
void Minimize(IWMClient &client)
void SetKeyboardHook(wxFrame *frame)
void OnFloatingPaneEndMove(CFloatingFrame &frame, CDockManager::EDragResult result, const wxPoint &sc_mouse_pos)
void RaiseFloatingInZOrder()
bool IsMinimized(IWMClient &client) const
void OnMove(wxMoveEvent &event)
void OnFloatingPaneMoving(CFloatingFrame &frame, const wxPoint &sc_mouse_pos)
CFloatingFrame * x_MoveToFloatingFrame(IDockableWindow &dockable, bool shift)
wxPoint m_PrevDragPos
bool IsFloating(IWMClient &client) const
virtual ~CDockManager()
void ApplyLayout(const objects::CUser_object &object)
CDockPanel - a container with a title bar (caption) hosting a single client window (IWMClient).
Definition: dock_panel.hpp:73
void RemoveClient(wxWindow *new_parent)
disconnect the client and re-parent it to the given window
Definition: dock_panel.cpp:208
virtual wxSize ClientToWindowSize(const wxSize &size) const
Definition: dock_panel.cpp:124
IWMClient * GetClient()
Definition: dock_panel.hpp:93
virtual CDockContainer * GetDockContainer()
Definition: dock_panel.cpp:499
virtual bool Destroy()
virtual CDockContainer * GetDockContainer()
virtual void SetDockContainer(CDockContainer *dock_cont)
list< CRef< CDockContainerDescr > > TItems
Definition: mru_list.hpp:53
const TItems & GetItems() const
Definition: mru_list.hpp:96
void SetItems(const TItems &items)
Definition: mru_list.hpp:110
void AddItem(T item)
Definition: mru_list.hpp:60
CMinPanelContainer.
void RemoveClient(CDockPanel &panel)
bool HasClient(CDockPanel &panel) const
void AddClient(CDockPanel &panel)
CRef –.
Definition: ncbiobj.hpp:618
CUICommandRegistry is a centralized registry where all application commands should be registered.
Definition: ui_command.hpp:146
static CUICommandRegistry & GetInstance()
the main instance associated with the application
Definition: ui_command.cpp:176
wxMenuItem * AppendMenuItem(wxMenu &menu, TCmdID cmd_id) const
Definition: ui_command.cpp:300
CUser_object & AddField(const string &label, const string &value, EParseField parse=eParse_String)
add a data field to the user object that holds a given value
CWindowManager - component controlling windowing of client windows.
wxFrame * GetMainWindow()
bool OnCloseClientsRequest(const TClients &clients)
bool OnCaptionPanelCommand(CDockPanel &panel, TCmdID cmd)
virtual bool AddClient(IWMClient &client, bool bFloat)
adds the client to the Main Tabbed Pane
string GetNewFloatingFrameTitle()
set< string > & m_Views
void operator()(CDockLayoutTree::CNode &node)
FClientFinder(set< string > &views)
IDockManagerKeyHook.
virtual void ForwardKeyEventsTo(CDockManager *manager)=0
IDockableWindow - repersents a window that can be docked in Dock Manager.
Definition: dock_window.hpp:53
virtual CDockContainer * GetDockContainer()=0
IWMClientFactory - IWMClient factory.
Definition: wm_client.hpp:133
virtual IWMClient * CreateClient(const TFingerprint &fingerprint, wxWindow *parent)=0
creates a client by fingerprint returns NULL if fingerprint is not recognized.
CFingerprint identifies an instance of IWMClient and is used for labeling layout positions.
Definition: wm_client.hpp:58
const string GetId() const
IWClient - abstract Window Manager client.
Definition: wm_client.hpp:50
virtual wxWindow * GetWindow()=0
returns a pointer to the wxWindow representing the client
virtual CFingerprint GetFingerprint() const =0
returns a fingerprint identifying the client
virtual bool IsAForm() const
returns true if client is a Form - wants to be sized to its client area (like a dialog)
Definition: wm_client.hpp:119
iterator_bool insert(const value_type &val)
Definition: set.hpp:149
static CS_COMMAND * cmd
Definition: ct_dynamic.c:26
#define WM_POST(text)
USING_SCOPE(objects)
const int kMaxContainers
static const char * kLayoutTag2
static const char * kVideoIdTag
static const char * kContainersTag
Saving and Loading layouts.
@ eCmdWindowFloat
Definition: dock_panel.hpp:56
@ eCmdCloseDockPanel
Definition: dock_panel.hpp:54
@ eCmdMoveToMainTab
Definition: dock_panel.hpp:55
@ eCmdWindowMinimize
Definition: dock_panel.hpp:57
@ eCmdWindowRestore
Definition: dock_panel.hpp:58
EDockEffect
EDockEffect.
Definition: dock_window.hpp:65
@ eNoEffect
Definition: dock_window.hpp:66
#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 REVERSE_ITERATE(Type, Var, Cont)
ITERATE macro to reverse sequence through container elements.
Definition: ncbimisc.hpp:827
#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
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
#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
int TCmdID
@ eCmdParentMove
Definition: command.hpp:117
@ eCmdReCreate
tool tip parent window about to dock
Definition: command.hpp:119
@ eCmdSuspend
tool tip window parent moves
Definition: command.hpp:118
@ eCmdDockMainWindow
tool tip parent window finished docking
Definition: command.hpp:120
TObjectType * Release(void)
Release a reference to the object and return a pointer to the object.
Definition: ncbiobj.hpp:846
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
void SetType(TType &value)
Assign a value to Type data member.
@ eCmdSetClientColor
int i
const struct ncbi::grid::netcache::search::fields::SIZE size
Int4 delta(size_t dimension_, const Int4 *score_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
static CNamedPipeClient * client
Definition: inftrees.h:24
#define _ASSERT
else result
Definition: token2.c:20
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
wxString ToWxString(const string &s)
Definition: wx_utils.hpp:173
string GetVideoId()
Returns id of video configuration to be used for saving settings.
Definition: wx_utils.cpp:224
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
wxRect GetScreenRect(const wxWindow &win)
Definition: wx_utils.cpp:783
Modified on Fri Dec 01 04:49:00 2023 by modify_doxy.py rev. 669887