/* * =========================================================================== * PRODUCTION $Log: command.cpp,v $ * PRODUCTION Revision 1000.2 2004/06/01 21:04:46 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.6 * PRODUCTION * =========================================================================== */ /* $Id: command.cpp,v 1000.2 2004/06/01 21:04:46 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors: Andrey Yazhuk * CCommandTarget - a class capable of handling commands using command maps. * CMenuBar - wrapps and extends Fl_Menu_Bar class. */ #include #include #include #include #include BEGIN_NCBI_SCOPE /// Traverses a list of Command Maps in order to locate a handler corresponding /// to the given command ID. const SCmdMapEntry* FindEntryByCmdID(const SCmdMap* pMap, TCmdID CmdID, SCmdMapEntry::EHandlerType type) { const SCmdMapEntry* pEntry = 0; while(pMap) { for( pEntry = pMap->m_Entries; pEntry->m_CmdID != 0; pEntry++ ) { if(CmdID >= pEntry->m_CmdID && CmdID m_LastCmdID && pEntry->m_HandlerType == type) return pEntry; // handler is found } pMap = pMap->m_BaseMap; // go to the command map of the base class } return NULL; // handler not found } //////////////////////////////////////////////////////////////////////////////// // class CCommandTarget const SCmdMap CCommandTarget::sm_CmdMap = { NULL, // no base class &CCommandTarget::sm_CmdMapEntries[0] }; const SCmdMap* CCommandTarget::GetCommandMap() const { return &CCommandTarget::sm_CmdMap; } const SCmdMapEntry CCommandTarget::sm_CmdMapEntries[] = { { 0, 0, SCmdMapEntry::eInvalid, 0 } // no entries }; void CCommandTarget::OnFlMenuCommand(Fl_Menu_* f_menu, void* user_data) { IMenu* menu = dynamic_cast(f_menu); if(menu) { CCommandTarget* target = menu->GetCmdTarget(); if(target) { TCmdID id = *((TCmdID*) user_data); //### temp target->OnCommand(id); } else { ERR_POST(Error IMenu should have a root CCommandTarget."); } } else { ERR_POST(Error used only with \"IMenu*\" menus."); } } bool CCommandTarget::OnCommand(const TCmdID CmdID) { bool b_handled = x_HandleCommand(CmdID); if(! b_handled) { b_handled = x_ChildrenHandleCommand(CmdID); // pass to children } return b_handled; } bool CCommandTarget::OnUpdateCommand(const TCmdID CmdID, ICmdUI* pCmdUI) { bool b_handled = x_UpdateCommand(CmdID, pCmdUI); if(! b_handled) { b_handled = x_ChildrenUpdateCommand(CmdID, pCmdUI); // pass to children } return b_handled; } bool CCommandTarget::AddChildCmdTarget(CCommandTarget* target) { if(target && find(m_ChildTargets.begin(), m_ChildTargets.end(), target) == m_ChildTargets.end()) { m_ChildTargets.push_back(target); return true; } return false; } bool CCommandTarget::RemoveChildCmdTarget(CCommandTarget* target) { if(target) { TChildTargets::iterator it = find(m_ChildTargets.begin(), m_ChildTargets.end(), target); if(it != m_ChildTargets.end()) { m_ChildTargets.erase(it); return true; } } return false; } bool CCommandTarget::x_HandleCommand(const TCmdID cmd) { const SCmdMapEntry *pEntry = FindEntryByCmdID(GetCommandMap(), cmd, SCmdMapEntry::eCmd); if(pEntry && pEntry->m_Handler) { if(pEntry->m_LastCmdID > pEntry->m_CmdID) { // range handler FCmdHandler_ID handler = (FCmdHandler_ID) pEntry->m_Handler; (this->*handler)(cmd); } else { FCmdHandler handler = pEntry->m_Handler; (this->*handler)(); } return true; } else return false; } bool CCommandTarget::x_UpdateCommand(const TCmdID cmd, ICmdUI* pCmdUI) { const SCmdMapEntry *pEntry = FindEntryByCmdID(GetCommandMap(), cmd, SCmdMapEntry::eUpdateCmd); if(pEntry && pEntry->m_Handler) { FUpdateCmdHandler handler = (FUpdateCmdHandler) pEntry->m_Handler; (*this.*handler)(pCmdUI); return true; } else return false; } bool CCommandTarget::x_ChildrenHandleCommand(const TCmdID cmd) { NON_CONST_ITERATE(TChildTargets, it, m_ChildTargets) { if((*it)->OnCommand(cmd)) return true; } return false; } bool CCommandTarget::x_ChildrenUpdateCommand(const TCmdID cmd, ICmdUI* pCmdUI) { NON_CONST_ITERATE(TChildTargets, it, m_ChildTargets) { if((*it)->OnUpdateCommand(cmd, pCmdUI)) return true; } return false; } END_NCBI_SCOPE /* * =========================================================================== * $Log: command.cpp,v $ * Revision 1000.2 2004/06/01 21:04:46 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.6 * * Revision 1.6 2004/05/21 22:27:50 gorelenk * Added PCH ncbi_pch.hpp * * Revision 1.5 2004/05/03 19:41:01 yazhuk * Extended command handling to support command updates * * Revision 1.4 2004/01/15 20:08:07 yazhuk * Moved most menu-related code to gui/widgets/gl/menu.cpp * * Revision 1.3 2004/01/08 19:36:51 yazhuk * Added to CCommandTarget support for child targets. Added MENU_SEPARATOR macro. * Added comments. * * revision 1.2 2003/10/15 21:14:24 yazhuk * Fixed GCC warning * * revision 1.1 2003/10/03 16:01:38 yazhuk * Initial revision * * =========================================================================== */