src/gui/widgets/wx/window_manager.cpp

Go to the documentation of this file.
00001 /*  $Id: window_manager.cpp 20439 2009-11-24 23:53:23Z dicuccio $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Authors:  Andrey Yazhuk
00027  *
00028  * File Description:
00029  */
00030 
00031 #include <ncbi_pch.hpp>
00032 
00033 
00034 #include <gui/widgets/wx/window_manager.hpp>
00035 
00036 #include <gui/widgets/wx/dock_manager.hpp>
00037 #include <gui/widgets/wx/dock_container.hpp>
00038 #include <gui/widgets/wx/dock_notebook.hpp>
00039 #include <gui/widgets/wx/dock_panel.hpp>
00040 #include <gui/widgets/wx/min_panel_container.hpp>
00041 
00042 #include <gui/widgets/wx/windows_dlg.hpp>
00043 #include <gui/widgets/wx/ui_command.hpp>
00044 #include <gui/widgets/wx/wx_utils.hpp>
00045 #include <gui/widgets/wx/fileartprov.hpp>
00046 
00047 #include <gui/utils/menu_item.hpp>
00048 
00049 #include <algorithm>
00050 
00051 #include <wx/sizer.h>
00052 #include <wx/menu.h>
00053 #include <wx/toolbar.h>
00054 
00055 
00056 BEGIN_NCBI_SCOPE
00057 
00058 ///////////////////////////////////////////////////////////////////////////////
00059 /// IWMClient::CFingerprint
00060 IWMClient::CFingerprint::CFingerprint()
00061 :   m_Persistent(false)
00062 {
00063 }
00064 
00065 
00066 IWMClient::CFingerprint::CFingerprint(const string& id, bool persistent)
00067 :   m_Id(id),
00068     m_Persistent(persistent)
00069 {
00070 }
00071 
00072 
00073 IWMClient::CFingerprint::CFingerprint(const CFingerprint& orig)
00074 :   m_Id(orig.m_Id),
00075     m_Persistent(orig.m_Persistent)
00076 {
00077 }
00078 
00079 
00080 bool IWMClient::CFingerprint::operator==(const CFingerprint& orig) const
00081 {
00082     return m_Id == orig.m_Id;
00083 }
00084 
00085 
00086 bool IWMClient::CFingerprint::IsEmpty() const
00087 {
00088     return m_Id.empty();
00089 }
00090 
00091 
00092 string IWMClient::CFingerprint::AsPersistentString() const
00093 {
00094     return m_Persistent ? m_Id : kEmptyStr;
00095 }
00096 
00097 
00098 void IWMClient::CFingerprint::FromPersistentString(const string& s)
00099 {
00100     m_Id = s;
00101     m_Persistent = ! s.empty();
00102 }
00103 
00104 
00105 ///////////////////////////////////////////////////////////////////////////////
00106 /// CWindowManagerEvent
00107 
00108 CWindowManagerEvent::CWindowManagerEvent(EEventType type, IWMClient* client)
00109 :   CEvent(type),
00110     m_Client(client),
00111     m_Cmd(eCmdInvalid)
00112 {
00113 }
00114 
00115 CWindowManagerEvent::CWindowManagerEvent(IWMClient* client, TCmdID cmd)
00116 :   CEvent(ePostCommand),
00117     m_Client(client),
00118     m_Cmd(cmd)
00119 {
00120 }
00121 
00122 
00123 CWindowManagerEvent::CWindowManagerEvent(EEventType type, const vector<IWMClient*>& clients)
00124 :   CEvent(type),
00125     m_Client(NULL),
00126     m_Clients(clients),
00127     m_Cmd(eCmdInvalid)
00128 {
00129     _ASSERT(type == eCloseClientsRequest);
00130 }
00131 
00132 
00133 IWMClient* CWindowManagerEvent::GetClient()
00134 {
00135     return m_Client;
00136 }
00137 
00138 
00139 void CWindowManagerEvent::GetClients(vector<IWMClient*>& clients)
00140 {
00141     clients = m_Clients;
00142 }
00143 
00144 
00145 ///////////////////////////////////////////////////////////////////////////////
00146 /// CWindowManager
00147 
00148 /// wxEvtHandler table
00149 BEGIN_EVENT_TABLE(CWindowManager, wxPanel)
00150     EVT_MENU_RANGE(eCmdWindowXXXX, eCmdWindowLast, CWindowManager::OnActivateWindow)
00151     EVT_MENU(eCmdShowWindowsDlg, CWindowManager::OnShowWindowsDlg)
00152     EVT_MENU_RANGE(eCmdCloseDockPanel, eCmdWindowRestore,
00153                    CWindowManager::OnWindowCommand)
00154     EVT_UPDATE_UI_RANGE(eCmdCloseDockPanel, eCmdWindowRestore,
00155                    CWindowManager::OnUpdateWindowCommand)
00156 
00157     EVT_LEFT_UP(CWindowManager::OnLeftUp)
00158     EVT_MOTION(CWindowManager::OnMotion)
00159     EVT_MOUSE_CAPTURE_LOST(CWindowManager::OnMouseCaptureLost)
00160 END_EVENT_TABLE()
00161 
00162 /// CEventHandler map
00163 BEGIN_EVENT_MAP(CWindowManager, CEventHandler)
00164     ON_EVENT(CWindowManagerEvent, CWindowManagerEvent::ePostCommand,
00165              &CWindowManager::OnPostCommand)
00166     ON_EVENT(CWindowManagerEvent, CWindowManagerEvent::eCloseClientsRequest,
00167              &CWindowManager::OnCloseClientsRequestEvent)
00168 END_EVENT_MAP()
00169 
00170 
00171 CWindowManager::CWindowManager(wxFrame* frame)
00172 :   wxPanel(),
00173     m_Advisor(NULL),
00174     m_MenuListener(NULL),
00175     m_FrameWindow(frame),
00176     m_DockManager(NULL),
00177     m_SavedFocus(NULL),
00178     m_SavedFocusPanel(NULL),
00179     m_ActiveClient(NULL),
00180     m_ActiveClientTarget(NULL),
00181     m_ClientFactory(NULL),
00182     m_DragDockPanel(NULL),
00183     m_IsDragging(false),
00184     m_Canceled(false)
00185 {
00186     SetSizer(new wxBoxSizer(wxVERTICAL));
00187 
00188     wxAuiDockArt* dock_art = m_AuiManager.GetArtProvider();
00189     dock_art->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 0);
00190 }
00191 
00192 
00193 void CWindowManager::RegisterImageAliases(wxFileArtProvider& provider)
00194 {
00195     provider.RegisterFileAlias(_T("wm_menu"), _T("wm_menu.png"));
00196     provider.RegisterFileAlias(_T("wm_menu_active"), _T("wm_menu_active.png"));
00197 
00198     provider.RegisterFileAlias(_T("wm_minimize"), _T("wm_minimize.png"));
00199     provider.RegisterFileAlias(_T("wm_minimize_active"), _T("wm_minimize_active.png"));
00200 
00201     provider.RegisterFileAlias(_T("wm_float"), _T("wm_float.png"));
00202     provider.RegisterFileAlias(_T("wm_float_active"), _T("wm_float_active.png"));
00203 
00204     provider.RegisterFileAlias(_T("wm_close"), _T("wm_close.png"));
00205     provider.RegisterFileAlias(_T("wm_close_active"), _T("wm_close_active.png"));
00206 }
00207 
00208 
00209 // this function delegates client creation to m_ClientFactory and then
00210 // registers the client
00211 IWMClient* CWindowManager::CreateClient(const TFingerprint& fingerprint,
00212                                         wxWindow* parent)
00213 {
00214     if(m_ClientFactory  &&  ! fingerprint.IsEmpty())   {
00215         IWMClient* client = m_ClientFactory->CreateClient(fingerprint, parent);
00216         _ASSERT(client);
00217         if(client)  {
00218             x_RegisterClient(*client);
00219         }
00220         return client;
00221     }
00222     return NULL;
00223 }
00224 
00225 
00226 void CWindowManager::SetRegistryPath(const string& reg_path)
00227 {
00228     m_RegPath = reg_path;
00229 }
00230 
00231 
00232 bool CWindowManager::Create(wxWindow *parent, wxWindowID id,
00233                             const wxPoint& pos, const wxSize& size)
00234 {
00235     bool res = wxPanel::Create(parent, id, pos, size, wxBORDER_NONE, _T("window_manager"));
00236     if(res) {
00237         m_AuiManager.SetManagedWindow(m_FrameWindow);
00238 
00239         wxAuiPaneInfo info;
00240         info.CenterPane();
00241 
00242         m_AuiManager.AddPane(this, info);
00243 
00244         m_DockManager = new CDockManager(*this, *this);
00245         m_DockManager->SetKeyboardHook(m_FrameWindow);
00246 
00247         // create the main Dock Container that will be hosted inside Window Manager
00248         CDockContainer* dock_cont = m_DockManager->GetMainContainer();
00249         GetSizer()->Add(dock_cont, 1, wxEXPAND);
00250 
00251         // create a container for minimized Clients
00252         CMinPanelContainer* cont = m_DockManager->GetMinPanelContainer();
00253         GetSizer()->Add(cont, 0, wxEXPAND);
00254 
00255         m_AuiManager.Update();
00256     }   
00257 
00258     return res;
00259 }
00260 
00261 
00262 CWindowManager::~CWindowManager()
00263 {
00264     CloseAllClients();
00265 
00266     m_AuiManager.UnInit();
00267 
00268     delete m_DockManager;
00269     m_DockManager = NULL;
00270 }
00271 
00272 
00273 void CWindowManager::SetAdvisor(IWindowManagerAdvisor* advisor)
00274 {
00275     m_Advisor = advisor;
00276 }
00277 
00278 
00279 void CWindowManager::SetMenuListener(IWindowManagerMenuListener* listener)
00280 {
00281     m_MenuListener = listener;
00282 }
00283 
00284 
00285 wxFrame* CWindowManager::GetFrameWindow()
00286 {
00287     return m_FrameWindow;
00288 }
00289 
00290 
00291 bool CWindowManager::AddClientInTab(IWMClient& client)
00292 {
00293     if(client.GetWindow())  {
00294         if(x_RegisterClient(client))    {
00295             m_DockManager->AddToDefaultLocation(client);
00296             x_ResetMenuBar();
00297         }
00298         return true;
00299     }
00300     return false;
00301 }
00302 
00303 
00304 void CWindowManager::MoveToMainTab(IWMClient& client)
00305 {
00306     m_DockManager->MoveToMainTab(client);
00307 }
00308 
00309 
00310 wxFrame* CWindowManager::MoveToFloatingFrame(IWMClient& client)
00311 {
00312     return m_DockManager->MoveToFloatingFrame(client);
00313 }
00314 
00315 
00316 void CWindowManager::Minimize(IWMClient& client)
00317 {
00318     return m_DockManager->Minimize(client);
00319 }
00320 
00321 
00322 void CWindowManager::Restore(IWMClient& client)
00323 {
00324     return m_DockManager->Restore(client);
00325 }
00326 
00327 
00328 bool CWindowManager::IsInMainTab(IWMClient& client) const
00329 {
00330     return m_DockManager->IsInMainTab(client);
00331 }
00332 
00333 
00334 bool CWindowManager::IsFloating(IWMClient& client) const
00335 {
00336     return m_DockManager->IsFloating(client);
00337 }
00338 
00339 
00340 bool CWindowManager::IsMinimized(IWMClient& client) const
00341 {
00342     return m_DockManager->IsMinimized(client);
00343 }
00344 
00345 
00346 /// max number of characters in the client labels shown in popups
00347 static const int kMaxClientLabel = 30;
00348 
00349 string CWindowManager::x_GetClientLabelForMenu(IWMClient& client)
00350 {
00351     string label = client.GetClientLabel();
00352     if((int) label.size() > kMaxClientLabel)  {
00353         label.resize(kMaxClientLabel);
00354         label += "...";
00355     }
00356     return label;
00357 }
00358 
00359 
00360 // handles commands originating from IDockPanel
00361 bool CWindowManager::OnCaptionPanelCommand(IDockPanel& panel, TCmdID cmd)
00362 {
00363     switch(cmd) {
00364     case eCmdCloseDockPanel:
00365     case eCmdMoveToMainTab:
00366     case eCmdWindowMinimize:
00367     case eCmdWindowRestore:
00368     case eCmdWindowFloat:   {
00369         /// these commands can affect window hierarchy and result in some windows
00370         /// being destroyed because of this we need to execute them
00371         /// asynchronously so that we do not destroy windows on the current call
00372         /// stack
00373         CRef<CEvent> evt(new CWindowManagerEvent(panel.GetClient(), cmd));
00374         Post(evt, CEventHandler::eDispatch_SelfOnly);
00375         return true;
00376     }
00377     case eCmdSetClientColor:
00378         return OnSetClientColor(panel);
00379     default:
00380         //_ASSERT(false);
00381         break;
00382     }
00383     return false;
00384 }
00385 
00386 
00387 bool CWindowManager::OnSetClientColor(IDockPanel& panel)
00388 {
00389     IWMClient* client = panel.GetClient();
00390     if (client)  {
00391         if(client->GetColor())   {
00392             // the client does support a notion of color
00393             CRgbaColor color = *client->GetColor();
00394             wxWindow* win = dynamic_cast<wxWindow*>(&panel);
00395             if (NcbiChooseColor(win, color)) {
00396                 client->SetColor(color);
00397                 win->Refresh();
00398             }
00399         }
00400     }
00401     return true;
00402 }
00403 
00404 
00405 bool CWindowManager::OnCloseClientsRequest(const TClients& clients)
00406 {
00407     CRef<CEvent> evt(new CWindowManagerEvent(CWindowManagerEvent::eCloseClientsRequest, clients));
00408     Send(evt, CEventHandler::eDispatch_SelfOnly);
00409     return true;
00410 }
00411 
00412 
00413 void CWindowManager::x_RemoveClient(IWMClient& client)
00414 {
00415     // check whether the client had focus
00416     bool reset = false;
00417     for (  wxWindow* w = m_SavedFocus;  w;  w = w->GetParent()) {
00418         if(w == m_SavedFocus)    {
00419             reset = true;
00420             break;
00421         }
00422     }
00423     if(reset)   {
00424         m_SavedFocus = NULL;
00425         m_SavedFocusPanel = NULL;
00426     }
00427 
00428     // reset active client
00429     if(&client == m_ActiveClient)   {
00430         m_ActiveClient = NULL;
00431         m_ActiveClientTarget = NULL;
00432 
00433         if(m_Advisor)   {
00434             m_Advisor->OnActiveClientChanged(m_ActiveClient);
00435         }
00436         x_ResetMenuBar();
00437     }
00438 
00439     // disconnect from command routing
00440     CEventHandler* target = dynamic_cast<CEventHandler*>(&client);
00441     if(target)  {
00442         RemoveListener(target);
00443     }
00444 
00445     // remove from the container
00446     m_DockManager->Remove(client);
00447 }
00448 
00449 
00450 bool CWindowManager::CloseClient(IWMClient& client)
00451 {
00452     if(x_CloseClient(client))   {
00453         x_ResetMenuBar();
00454         return true;
00455     }
00456     return false;
00457 }
00458 
00459 
00460 void CWindowManager::CloseClients(const TClients& clients)
00461 {
00462     for( size_t i = 0;  i < clients.size();  i++ )  {
00463         IWMClient& client = *clients[i];
00464         x_CloseClient(client);
00465     }
00466     x_ResetMenuBar();
00467 }
00468 
00469 
00470 void CWindowManager::CloseAllClients()
00471 {
00472     while( ! m_Clients.empty())  {
00473         IWMClient& client = *m_Clients.back();
00474         x_CloseClient(client);
00475     }
00476     x_ResetMenuBar();
00477 }
00478 
00479 
00480 // removes from Root Container, Unregisters and sends notification
00481 bool CWindowManager::x_CloseClient(IWMClient& client)
00482 {
00483     bool found = IsRegistered(client);
00484     _ASSERT(found);
00485 
00486     if(found) {
00487         _ASSERT(m_Advisor);
00488         if(m_Advisor)   {
00489             m_Advisor->OnClientAboutToClose(client);
00490         }
00491 
00492         x_RemoveClient(client);
00493 
00494         x_UnRegisterClient(client);
00495 
00496         if(m_Advisor)   {
00497             m_Advisor->OnClientClosed(client);
00498         }
00499         return true;
00500     } else {
00501         ERR_POST("CWindowManager::x_CloseClient() - client not registred, cannot close");
00502     }
00503     return false;
00504 }
00505 
00506 
00507 void CWindowManager::GetAllClients(vector<IWMClient*>& clients)
00508 {
00509     clients = m_Clients;
00510 }
00511 
00512 
00513 bool CWindowManager::IsRegistered(IWMClient& client) const
00514 {
00515     bool found = (std::find(m_Clients.begin(), m_Clients.end(), &client) != m_Clients.end());
00516     return found;
00517 }
00518 
00519 
00520 void CWindowManager::ActivateClient(IWMClient& client)
00521 {
00522     TClients clients;
00523     clients.push_back(&client);
00524     ActivateClients(clients);
00525 }
00526 
00527 
00528 // traverses all containers and adjusts tab panels so that clients become
00529 // visible
00530 void CWindowManager::ActivateClients(TClients& clients)
00531 {
00532     m_DockManager->ActivateClients(clients);
00533 }
00534 
00535 
00536 bool CWindowManager::HasToolBar(const string& name)
00537 {
00538     wxString wx_name = ToWxString(name);
00539     wxAuiPaneInfo& pane = m_AuiManager.GetPane(wx_name);
00540     return pane.IsOk();
00541 }
00542 
00543 
00544 void CWindowManager::AddToolBar(wxToolBar* toolbar)
00545 {
00546     _ASSERT(toolbar);
00547     if(toolbar) {
00548         wxAuiPaneInfo pane_info;
00549 
00550         wxString name = toolbar->GetName();
00551         pane_info.Name(name);
00552         pane_info.Caption(name);
00553 
00554         pane_info.ToolbarPane().Top();
00555         pane_info.TopDockable(true)
00556                  .LeftDockable(false)
00557                  .RightDockable(false)
00558                  .BottomDockable(false);
00559         pane_info.Resizable(false);
00560         pane_info.DestroyOnClose(true);
00561 
00562         m_AuiManager.AddPane(toolbar, pane_info);
00563         m_AuiManager.Update();
00564     }
00565 }
00566 
00567 
00568 void CWindowManager::DeleteToolBar(const string& name)
00569 {
00570     wxAuiPaneInfo& pane = m_AuiManager.GetPane(ToWxString(name));
00571     if(pane.IsOk()) {
00572         wxWindow* toolbar = pane.window;
00573         m_AuiManager.DetachPane(toolbar);
00574         toolbar->Destroy();
00575     }
00576 }
00577 
00578 
00579 IWMClient* CWindowManager::GetActiveClient()
00580 {
00581     return m_ActiveClient;
00582 }
00583 
00584 
00585 void CWindowManager::OnShowWindowsDlg(wxCommandEvent& event)
00586 {
00587     CWindowsDlg dlg;
00588 
00589     string path = CGuiRegistryUtil::MakeKey(m_RegPath, "Windows Dialog");
00590     dlg.SetRegistryPath(path);
00591 
00592     dlg.SetWindowManager(this);
00593 
00594     dlg.Create(this);
00595     dlg.ShowModal();
00596 }
00597 
00598 
00599 // creates entry in m_ClientToRec table if it does not exist
00600 bool CWindowManager::x_RegisterClient(IWMClient& client)
00601 {
00602     bool registered = IsRegistered(client);
00603     _ASSERT( ! registered);
00604 
00605     if( ! registered)   {
00606         m_Clients.push_back(&client);
00607         wxWindow* window = client.GetWindow();
00608 
00609         _ASSERT(window);
00610         _ASSERT(m_WindowToClient.find(window) == m_WindowToClient.end());
00611 
00612         m_WindowToClient[window] = &client;
00613         return true;
00614     }
00615     return false;
00616 }
00617 
00618 
00619 // deletes m_ClientToRec entry corresponding to the client
00620 bool CWindowManager::x_UnRegisterClient(IWMClient& client)
00621 {
00622     TClients::iterator it =
00623         std::find(m_Clients.begin(), m_Clients.end(), &client);
00624     if(it != m_Clients.end())   {
00625         wxWindow* window = client.GetWindow();
00626         m_WindowToClient.erase(window);
00627 
00628         m_Clients.erase(it);
00629         return true;
00630     }
00631     return false;
00632 }
00633 
00634 
00635 void CWindowManager::x_UpdateListener(IWMClient& client)
00636 {
00637     TEvent evt(TEvent::eClientChanged, &client);
00638     Send(&evt);
00639 }
00640 
00641 
00642 // backbone of the menu contributed to the main Menu Bar
00643 
00644 WX_DEFINE_MENU(sBaseMenu)
00645     WX_SUBMENU("&Window")
00646         WX_MENU_SEPARATOR_L("Actions")
00647         WX_MENU_ITEM(eCmdWindowMinimize)
00648         WX_MENU_ITEM(eCmdWindowFloat)
00649         WX_MENU_ITEM(eCmdMoveToMainTab)
00650         WX_MENU_SEPARATOR_L("Close")
00651         WX_MENU_ITEM(eCmdCloseDockPanel)
00652         WX_MENU_SEPARATOR_L("Actions2")
00653         WX_MENU_ITEM(eCmdShowWindowsDlg)
00654         WX_MENU_SEPARATOR_L("Windows")
00655     WX_END_SUBMENU()
00656 WX_END_MENU()
00657 
00658 
00659 const wxMenu* CWindowManager::GetMenu()
00660 {
00661     /// build on demand
00662     if( ! m_Menu.get())  {
00663         // create static backbone
00664         CUICommandRegistry& cmd_reg = CUICommandRegistry::GetInstance();
00665         m_Menu.reset(cmd_reg.CreateMenu(sBaseMenu));
00666 
00667         _ASSERT(m_Menu.get());
00668 
00669         // create dynamic part
00670         x_UpdateWindowsMenu(*m_Menu);
00671 
00672         // get menus from only active client
00673         if (m_ActiveClient) {
00674             const wxMenu* client_root = m_ActiveClient->GetMenu();
00675             if(client_root)    {
00676                 // merge Client's menu into Manager's menu
00677                 Merge(*m_Menu, *client_root);
00678             }
00679         }
00680 /*
00681         // get menus from clients
00682         ITERATE(TClients, it, m_Clients) {
00683             IWMClient* client = *it;
00684             const wxMenu* client_root = client->GetMenu();
00685             if(client_root)    {
00686                 // merge Client's menu into Manager's menu
00687                 Merge(*m_Menu, *client_root);
00688             }
00689         }
00690  */
00691     }
00692     return m_Menu.get();
00693 }
00694 
00695 
00696 // incrementally modify dynamic parts (if they have changed)
00697 void CWindowManager::UpdateMenuBar(wxMenu& menu)
00698 {
00699     // delete dynamic part and recreate it
00700     x_UpdateWindowsMenu(menu);
00701 }
00702 
00703 
00704 const static int    kMaxRecentItems = 10;
00705 
00706 // generate a menu item label with numeric access key "&N"
00707 inline string   GenerateWinItemPrefix(int index)
00708 {
00709     if(index < 10)  {
00710         return string("&" +  NStr::IntToString(index) + "  ");
00711     } else if(index == 10) {
00712         return "1&0  ";
00713     }
00714     return "    ";
00715 }
00716 
00717 
00718 void CWindowManager::x_UpdateWindowsMenu(wxMenu& root_menu)
00719 {
00720     m_CmdToWindow.clear();
00721 
00722     static wxString sWindow(_T("&Window"));
00723 
00724     wxMenuItem* win_item = ncbi::FindSubItem(root_menu, sWindow);
00725     wxMenu* win_menu = win_item ? win_item->GetSubMenu() : NULL;
00726 
00727     if(win_menu == NULL)    {
00728         // not found - create new one
00729         win_menu = new wxMenu(sWindow);
00730         root_menu.Append(wxID_ANY, win_menu->GetTitle(), win_menu);
00731     } else {
00732         // remove child items corresponding to windows
00733         wxMenuItemList& items = win_menu->GetMenuItems();
00734         for(wxMenuItemList::compatibility_iterator it = items.GetFirst();
00735                                                     it; ) {
00736             wxMenuItem* sub_item = it->GetData();
00737 
00738             wxMenuItemList::compatibility_iterator it_next = it->GetNext();
00739 
00740             if(sub_item->GetKind() == wxITEM_NORMAL)  {
00741                 TCmdID cmd = sub_item->GetId();
00742                 if(cmd >= eCmdWindowXXXX  &&  cmd <= eCmdWindowLast)    {
00743                     win_menu->Delete(sub_item);
00744                 }
00745             }
00746             it = it_next;
00747         }
00748     }
00749 
00750     // show first kMaxRecentItems clients in "Windows" menu
00751     int index = 0;
00752     string s;
00753     ITERATE(TClients, it, m_Clients) {
00754         IWMClient* client = *it;
00755 
00756         TCmdID cmd = eCmdWindowXXXX + index++;
00757         m_CmdToWindow[cmd] = client;
00758         s = GenerateWinItemPrefix(index) + x_GetClientLabelForMenu(*client);
00759         win_menu->Append(cmd, ToWxString(s));
00760 
00761         if(index >= kMaxRecentItems)    { // show no more then kMaxRecentItems items
00762             break;
00763         }
00764     }
00765 }
00766 
00767 void CWindowManager::OnFocusChanged( wxWindow* new_focus )
00768 {
00769     if( new_focus != m_SavedFocus ){
00770         // redraw captions for views affected by changes in focus
00771         if( m_SavedFocusPanel ){
00772             wxWindow* win = dynamic_cast<wxWindow*>( m_SavedFocusPanel );
00773             win->Refresh();
00774         }
00775 
00776         m_SavedFocus = new_focus;
00777         m_SavedFocusPanel = x_GetCaptionPanelByWindow( m_SavedFocus );
00778 
00779         x_SetActiveClient( m_SavedFocus );
00780     }
00781 }
00782 
00783 // update m_ActiveClient and  m_ActiveClientTarget to keep it in-sync with focus
00784 void   CWindowManager::x_UpdateActiveClient()
00785 {
00786     OnFocusChanged( FindFocus() );
00787 }
00788 
00789 void CWindowManager::x_SetActiveClient( wxWindow* focused )
00790 {
00791     // check if focused widget is our client or a child of our client
00792     for( 
00793         wxWindow* wid = focused; 
00794         wid != NULL && wid != this; 
00795         wid = wid->GetParent()
00796     ){
00797         IWMClient* client = GetClientByWindow( wid );
00798 
00799         if( !client || !IsRegistered( *client ) ){ 
00800             continue;
00801         }
00802             
00803         // this OUR client
00804         if( m_ActiveClient != client ){    
00805             m_ActiveClient = client;
00806             m_ActiveClientTarget = dynamic_cast<CEventHandler*>(m_ActiveClient);
00807 
00808             if( m_Advisor ){
00809                 m_Advisor->OnActiveClientChanged( m_ActiveClient );
00810             }
00811 
00812             x_ResetMenuBar();
00813         }
00814 
00815         break;
00816     }
00817 }
00818 
00819 
00820 bool CWindowManager::OnCommand(const TCmdID cmd)
00821 {
00822     x_UpdateActiveClient();
00823 
00824     bool b_handled = false;
00825 
00826     if(m_ActiveClientTarget) {
00827         b_handled = m_ActiveClientTarget->OnCommand(cmd);
00828     }
00829     if(! b_handled) {
00830         if (CEventHandler::OnCommand(cmd)) return true;
00831     }
00832     return b_handled;
00833 }
00834 
00835 
00836 void CWindowManager::OnActivateWindow( wxCommandEvent& event )
00837 {
00838     int cmd = event.GetId();
00839     IWMClient* client = m_CmdToWindow[cmd];
00840     ActivateClient(*client);
00841 }
00842 
00843 
00844 /// handles an internal command posted to itself
00845 void CWindowManager::OnPostCommand(CEvent* evt)
00846 {
00847     CWindowManagerEvent* wm_evt = dynamic_cast<CWindowManagerEvent*>(evt);
00848     _ASSERT(wm_evt  &&  wm_evt->GetClient());
00849 
00850     TCmdID cmd = wm_evt->GetCmd();
00851     IWMClient* client = wm_evt->GetClient();
00852 
00853     switch(cmd) {
00854     case eCmdCloseDockPanel:
00855     case eCmdMoveToMainTab:
00856     case eCmdWindowFloat:
00857     case eCmdWindowMinimize:
00858     case eCmdWindowRestore:
00859         x_HandlePanelCommand(*client, cmd);
00860         break;
00861 
00862     default:
00863         _ASSERT(false);
00864     }
00865 }
00866 
00867 
00868 // handles commands arriving from the application menu bar
00869 void CWindowManager::OnWindowCommand(wxCommandEvent& event)
00870 {
00871     IWMClient* client = GetActiveClient();
00872     if(client)  {
00873         x_HandlePanelCommand(*client, event.GetId());
00874     }
00875 }
00876 
00877 
00878 void CWindowManager::OnUpdateWindowCommand(wxUpdateUIEvent& event)
00879 {
00880     IWMClient* client = GetActiveClient();
00881     OnUpdateWindowCommand_Client(event, client);
00882 }
00883 
00884 
00885 void CWindowManager::OnUpdateWindowCommand_Client(wxUpdateUIEvent& event, IWMClient* client)
00886 {
00887     bool en = false;
00888     if(client)  {
00889         switch(event.GetId()) {
00890         case eCmdCloseDockPanel:
00891             en = true;
00892             break;
00893 
00894         case eCmdMoveToMainTab:
00895             en = m_DockManager->IsInMainTab(*client);
00896             break;
00897 
00898         case eCmdWindowFloat:
00899             en = ! m_DockManager->IsFloating(*client);
00900             break;
00901 
00902         case eCmdWindowMinimize:
00903             en = ! m_DockManager->IsMinimized(*client);
00904             break;
00905 
00906         case eCmdWindowRestore:
00907             en = m_DockManager->IsMinimized(*client);
00908             break;
00909 
00910         default:
00911             _ASSERT(false);
00912             break;
00913         }
00914     }
00915     event.Enable(en);
00916 }
00917 
00918 
00919 void CWindowManager::x_HandlePanelCommand(IWMClient& client, int cmd)
00920 {
00921     switch(cmd) {
00922     case eCmdCloseDockPanel:
00923         _ASSERT(m_Advisor);
00924         /// ask advisor to take necessary action
00925         if(m_Advisor) {
00926             TClients clients;
00927             clients.push_back(&client);
00928             m_Advisor->OnCloseClientsRequest(clients);
00929         }
00930         break;
00931 
00932     case eCmdMoveToMainTab:
00933         m_DockManager->MoveToMainTab(client);
00934         break;
00935 
00936     case eCmdWindowFloat:
00937         m_DockManager->MoveToFloatingFrame(client);
00938         break;
00939 
00940     case eCmdWindowMinimize:
00941         m_DockManager->Minimize(client);
00942         break;
00943 
00944     case eCmdWindowRestore:
00945         m_DockManager->Restore(client);
00946         break;
00947     default:
00948         _ASSERT(false);
00949         break;
00950     }
00951 }
00952 
00953 void CWindowManager::OnCloseClientsRequestEvent(CEvent* evt)
00954 {
00955     CWindowManagerEvent* wm_evt = dynamic_cast<CWindowManagerEvent*>(evt);
00956     _ASSERT(wm_evt);
00957     _ASSERT(m_Advisor);
00958 
00959     if(m_Advisor)   {
00960         TClients clients;
00961         wm_evt->GetClients(clients);
00962         m_Advisor->OnCloseClientsRequest(clients);
00963     }
00964 }
00965 
00966 
00967 IWMClient* CWindowManager::GetClientByWindow(wxWindow* widget)
00968 {
00969     IDockPanel* panel = dynamic_cast<IDockPanel*>(widget);
00970     if(panel)   {
00971         return panel->GetClient();
00972     } else {
00973         TWindowToClientMap::const_iterator it = m_WindowToClient.find(widget);
00974         return (it == m_WindowToClient.end()) ? NULL : it->second;
00975     }
00976 }
00977 
00978 string CWindowManager::GetNewFloatingFrameTitle()
00979 {
00980     if(m_Advisor)   {
00981         return m_Advisor->GetFloatingFrameTitle();
00982     } else {
00983         return kEmptyStr;
00984     }
00985 }
00986 
00987 void CWindowManager::RefreshClient( IWMClient& client )
00988 {
00989     bool found = IsRegistered( client );
00990     //_ASSERT(found); This is valid for composite view such as Multi-pane alignment view
00991     if( !found ) return;
00992 
00993     wxWindow* window = client.GetWindow();
00994     if( !window ) return;
00995 
00996 
00997     CDockPanel* panel = dynamic_cast<CDockPanel*>( window->GetParent() );
00998     if( !panel ) return;
00999 
01000     panel->UpdateCaption();
01001 
01002     wxWindow* parent = panel->GetParent();
01003     CDockNotebook* notebook = dynamic_cast<CDockNotebook*>( parent );
01004     if( notebook ){
01005         notebook->RefreshPageByWindow( panel );
01006     } else {
01007        parent->Layout();
01008        parent->Refresh();
01009     }
01010 }
01011 
01012 // for any given widget returns the parent Caption Panel
01013 IDockPanel* CWindowManager::x_GetCaptionPanelByWindow( wxWindow* widget )
01014 {
01015     //try {
01016         for( wxWindow* w = widget; w != NULL; ){
01017             IDockPanel* panel = dynamic_cast<IDockPanel*>(w);
01018             if( panel ){
01019                 return panel;
01020             }
01021             w = w->GetParent();
01022         }
01023     
01024     /*
01025     }catch(...) {
01026         ERR_POST("CWindowManager::x_GetCaptionPanelByWindow() - unhandled exception");
01027     }
01028     */
01029     return NULL;
01030 }
01031 
01032 
01033 bool CWindowManager::Dispatch( CEvent* evt, EDispatch disp_how, int pool )
01034 {
01035     if( disp_how == eDispatch_FirstHandler ){
01036         // try to deliver event to the active client
01037         IWMClient* client = GetActiveClient();
01038         CEventHandler* client_handler = dynamic_cast<CEventHandler*>(client);
01039 
01040         if(HasListener(client_handler, pool)) {
01041             return client_handler->Send(evt, disp_how, pool);
01042         }
01043     }
01044 
01045     // default pathway
01046     return CEventHandler::Dispatch(evt, disp_how, pool);
01047 }
01048 
01049 
01050 bool CWindowManager::ProcessEvent( wxEvent& event )
01051 {
01052     // Stops the same event being processed repeatedly
01053     static wxEventType inEvent = wxEVT_NULL;
01054     if( inEvent == event.GetEventType() ){
01055         return false;
01056     }
01057     inEvent = event.GetEventType();
01058     
01059     // Redirect events to active child first.
01060     bool res = false;
01061     if( event.IsCommandEvent() ){
01062         wxEventType type = event.GetEventType();
01063 
01064         if( type == wxEVT_UPDATE_UI || type == wxEVT_COMMAND_MENU_SELECTED ){
01065             IWMClient* client = GetActiveClient();
01066             if( client ){
01067 
01068                 wxEvtHandler* handler = client->GetCommandHandler();
01069                 _ASSERT(handler);
01070 
01071                 res = handler->ProcessEvent( event );
01072             }
01073         }
01074     }
01075     if( !res ){
01076         res = TParent::ProcessEvent( event );
01077     }
01078 
01079     inEvent = wxEVT_NULL;
01080     return res;
01081 }
01082 
01083 
01084 objects::CUser_object* CWindowManager::SaveLayout()
01085 {
01086     objects::CUser_object* layout = m_DockManager->SaveLayout();
01087     return layout;
01088 }
01089 
01090 
01091 void CWindowManager::ApplyLayout( const objects::CUser_object& layout )
01092 {
01093     m_DockManager->ApplyLayout( layout );
01094 
01095     x_ResetMenuBar();
01096 }
01097 
01098 
01099 void CWindowManager::LoadLayout( const objects::CUser_object& layout, IWMClientFactory& factory )
01100 {
01101     m_ClientFactory = &factory;
01102 
01103     // Window Manager works as a proxy for m_ClientFactory
01104     m_DockManager->LoadLayout( layout, *this );
01105 
01106     m_ClientFactory = NULL;
01107 
01108     x_ResetMenuBar();
01109 }
01110 
01111 
01112 void CWindowManager::x_ResetMenuBar()
01113 {
01114     m_Menu.reset(); // delete the old one
01115 
01116     if( m_MenuListener ){
01117         m_MenuListener->UpdateMenuBar(); // request Menu Bar update
01118     }
01119 }
01120 
01121 
01122 void CWindowManager::OnDockPanelStartDrag( CDockPanel* panel, const wxPoint& pt )
01123 {
01124     m_DragDockPanel = panel;
01125 
01126     // translate mouse position into local (client) coordinate system
01127     wxPoint sc_mouse_pos = m_DragDockPanel->ClientToScreen(pt);
01128     m_ClickPoint = ScreenToClient(sc_mouse_pos);
01129     m_IsDragging = true;
01130 
01131     /// capture mouse to receive all mouse events - now we handle the mouse
01132     CaptureMouse();
01133 
01134     x_OnBeginDrag(m_ClickPoint);
01135 }
01136 
01137 
01138 void CWindowManager::OnMotion(wxMouseEvent& evt)
01139 {
01140     wxPoint pt = evt.GetPosition();
01141     //WM_POST("CWindowManager::OnMotion()  " << pt.x << " " << pt.y);
01142 
01143     if(m_IsDragging) {
01144         if ( ! evt.LeftIsDown())    {
01145             x_OnEndDrag(pt, CDockManager::eDrop);
01146         } else {
01147             x_OnDrag(pt);
01148         }
01149     }
01150 }
01151 
01152 
01153 void CWindowManager::OnLeftUp(wxMouseEvent& evt)
01154 {
01155     wxPoint pt = evt.GetPosition();
01156     //WM_POST("CWindowManager::OnLeftUp()  " << pt.x << " " << pt.y);
01157 
01158     if (HasCapture())   {
01159         //WM_POST("ReleaseMouse()");
01160         ReleaseMouse();
01161     }
01162 
01163     if (m_IsDragging)   {
01164         x_OnEndDrag(pt, CDockManager::eDrop);
01165     }
01166 }
01167 
01168 
01169 void CWindowManager::OnMouseCaptureLost(wxMouseCaptureLostEvent& evt)
01170 {
01171     //WM_POST("CWindowManager::OnMouseCaptureLost()");
01172     if (m_IsDragging)   {
01173         wxPoint pt = ::wxGetMousePosition();
01174         x_OnEndDrag(pt, CDockManager::eCancel);
01175     }
01176 }
01177 
01178 
01179 void CWindowManager::x_OnBeginDrag(const wxPoint& mouse_pos)
01180 {
01181     //WM_POST("CWindowManager::x_OnBeginDrag()");
01182 
01183     m_IsDragging = true;
01184     wxPoint sc_mouse_pos = ClientToScreen(mouse_pos);
01185     m_DockManager->OnBeginDrag(*m_DragDockPanel, sc_mouse_pos);
01186 }
01187 
01188 
01189 void CWindowManager::x_OnDrag(const wxPoint& mouse_pos)
01190 {
01191     //WM_POST("CWindowManager::x_OnDrag()");
01192 
01193     wxPoint sc_mouse_pos = ClientToScreen(mouse_pos);
01194     bool ok = m_DockManager->OnDrag(*m_DragDockPanel, sc_mouse_pos);
01195 
01196     if( ! ok) {
01197         // dragging has been canceled
01198         //WM_POST("CWindowManager::x_OnDrag() ok = false - canceling");
01199 
01200         m_Canceled = true;
01201         ReleaseMouse();
01202         //WM_POST("ReleaseMouse()");
01203 
01204         m_IsDragging = false;
01205 
01206         m_DragDockPanel->FinishDrag();
01207     }
01208 }
01209 
01210 
01211 void CWindowManager::x_OnEndDrag(const wxPoint& mouse_pos, CDockManager::EDragResult result)
01212 {
01213     //LOG_POST("CWindowManager::x_OnEndDrag()");
01214     wxPoint sc_mouse_pos = ClientToScreen(mouse_pos);
01215     m_DockManager->OnEndDrag(*m_DragDockPanel, result, sc_mouse_pos);
01216     m_IsDragging = false;
01217 
01218     m_DragDockPanel->FinishDrag();
01219 }
01220 
01221 
01222 END_NCBI_SCOPE
01223 
01224 

Generated on Sun Dec 6 22:32:39 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:21:05 2009 by modify_doxy.py rev. 173732