📄 wg_menu.cpp
字号:
// wg_menu.cpp//// CMenu implementation////// Copyright (c) 2002 Rob Wiskow// rob-dev@boxedchaos.com//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//#include "wgui_include_config.h"#include "wg_menu.h"#include "std_ex.h"#include "wg_application.h"#include "wg_message_server.h"#include "wg_debug.h"#include "wg_error.h"namespace wGui{// CMenuBaseCMenuBase::CMenuBase(const CRect& WindowRect, CWindow* pParent, CFontEngine* pFontEngine) : CWindow(WindowRect, pParent), m_pHighlightedItem(0), m_bCachedRectsValid(false), m_pActivePopup(0), m_hRightArrowBitmap(WGRES_RIGHT_ARROW_BITMAP), m_HighlightColor(COLOR_DARKGRAY){ m_sClassName = "CMenuBase"; if (pFontEngine) { m_pFontEngine = pFontEngine; } else { m_pFontEngine = CApplication::Instance()->GetDefaultFontEngine(); } CMessageServer::Instance().RegisterMessageClient(this, CMessage::MOUSE_MOVE); CMessageServer::Instance().RegisterMessageClient(this, CMessage::CTRL_LCLICK); CMessageServer::Instance().RegisterMessageClient(this, CMessage::CTRL_TIMER); m_pPopupTimer = new CTimer(this);}CMenuBase::~CMenuBase(void){}void CMenuBase::InsertMenuItem(const SMenuItem& MenuItem, int iPosition){ m_MenuItems.insert((iPosition == -1) ? m_MenuItems.end() : m_MenuItems.begin() + iPosition, std::make_pair(MenuItem, std::make_pair(CRenderedString(m_pFontEngine, MenuItem.sItemText, CRenderedString::VALIGN_TOP), CRect()))); m_bCachedRectsValid = false;}void CMenuBase::RemoveMenuItem(int iPosition){ m_MenuItems.erase(m_MenuItems.begin() + iPosition); m_bCachedRectsValid = false; StartDrawProc();}void CMenuBase::HideActivePopup(void){ if (m_pActivePopup) { m_pActivePopup->Hide(); m_pActivePopup = 0; }}bool CMenuBase::OnMouseButtonDown(CPoint Point, unsigned int Button){ // We cant do quite the same thing as normal since children of menus don't appear inside their bounds bool bResult = false; if (m_bVisible) { for (std::list<CWindow*>::reverse_iterator iter = m_ChildWindows.rbegin(); iter != m_ChildWindows.rend(); ++iter) { bResult = (*iter)->OnMouseButtonDown(Point, Button); if (bResult) { break; } } } return bResult;}bool CMenuBase::HandleMessage(CMessage* pMessage){ bool bHandled = false; if (pMessage) { switch(pMessage->MessageType()) { case CMessage::MOUSE_MOVE: { CMouseMessage* pMouseMessage = dynamic_cast<CMouseMessage*>(pMessage); if (m_bVisible && pMouseMessage && m_WindowRect.HitTest(pMouseMessage->Point) == CRect::RELPOS_INSIDE) { UpdateCachedRects(); SMenuItem* pOldHighlight = m_pHighlightedItem; m_pHighlightedItem = 0; for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (iter->second.second.HitTest(pMouseMessage->Point) == CRect::RELPOS_INSIDE && !iter->first.bSpacer) { if (m_pHighlightedItem != &(iter->first)) { m_pPopupTimer->StopTimer(); m_pHighlightedItem = &(iter->first); if (iter->first.pPopup) { m_pPopupTimer->StartTimer(1000); } } break; } } if (pOldHighlight != m_pHighlightedItem) { TraceIf(m_pHighlightedItem != 0, "Menu Highlight Item Changed to : " + (m_pHighlightedItem ? m_pHighlightedItem->sItemText : std::string(""))); StartDrawProc(); } } else if (m_pHighlightedItem != 0) { m_pPopupTimer->StopTimer(); m_pHighlightedItem = 0; StartDrawProc(); } break; } case CMessage::CTRL_LCLICK: { TIntMessage* pCtrlMessage = dynamic_cast<TIntMessage*>(pMessage); if (pCtrlMessage && pCtrlMessage->Destination() == this) { for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (pCtrlMessage->Source() == iter->first.pPopup) { CMessageServer::Instance().QueueMessage(new TIntMessage(CMessage::CTRL_LCLICK, m_pParentWindow, this, pCtrlMessage->Value())); bHandled = true; break; } } } break; } case CMessage::CTRL_TIMER: { if (pMessage->Destination() == this) { bHandled = true; } break; } default : bHandled = CWindow::HandleMessage(pMessage); break; } } return bHandled;}// CMenuCMenu::CMenu(const CRect& WindowRect, CWindow* pParent, CFontEngine* pFontEngine) : CMenuBase(WindowRect, pParent, pFontEngine){ m_sClassName = "CMenu"; CMessageServer::Instance().RegisterMessageClient(this, CMessage::MOUSE_MOVE);}CMenu::~CMenu(void){}void CMenu::InsertMenuItem(const SMenuItem& MenuItem, int iPosition){ m_MenuItems.insert((iPosition == -1) ? m_MenuItems.end() : m_MenuItems.begin() + iPosition, std::make_pair(MenuItem, std::make_pair(CRenderedString(m_pFontEngine, MenuItem.sItemText, CRenderedString::VALIGN_NORMAL), CRect()))); m_bCachedRectsValid = false; if (MenuItem.pPopup) { MenuItem.pPopup->SetParentMenu(this); }}void CMenu::Draw(void) const{ CWindow::Draw(); CPainter Painter(m_pSDLSurface); UpdateCachedRects(); for (t_MenuItemVector::const_iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (m_pHighlightedItem == &(iter->first)) { Painter.DrawRect(iter->second.second, true, m_HighlightColor, m_HighlightColor); } CRect TextRect(iter->second.second); TextRect.Grow(-2); if (iter->first.bSpacer) { Painter.DrawVLine(TextRect.Top(), TextRect.Bottom(), TextRect.Left(), COLOR_LIGHTGRAY); Painter.DrawVLine(TextRect.Top(), TextRect.Bottom(), TextRect.Right(), COLOR_DARKGRAY); } else iter->second.first.Draw(m_pSDLSurface, TextRect, CPoint(TextRect.Left(), (TextRect.Top() + TextRect.Bottom()) * 3 / 4)); }}bool CMenu::OnMouseButtonDown(CPoint Point, unsigned int Button){ bool bResult = false; if (! CMenuBase::OnMouseButtonDown(Point, Button) && m_bVisible && (m_WindowRect.HitTest(Point) == CRect::RELPOS_INSIDE) && (Button == CMouseMessage::LEFT)) { UpdateCachedRects(); for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (iter->second.second.HitTest(Point) == CRect::RELPOS_INSIDE && !iter->first.bSpacer) { HideActivePopup(); if (iter->first.pPopup) { CPopupMenu* pPopup = dynamic_cast<CPopupMenu*>(iter->first.pPopup); if (pPopup) { m_pActivePopup = pPopup; ShowActivePopup(iter->second.second, GetAncestor(ROOT)->GetClientRect()); } } else { CMessageServer::Instance().QueueMessage(new TIntMessage(CMessage::CTRL_LCLICK, m_pParentWindow, this, iter->first.iItemId)); } break; } } bResult = true; } return bResult;}bool CMenu::HandleMessage(CMessage* pMessage){ bool bHandled = false; if (pMessage) { switch(pMessage->MessageType()) { case CMessage::MOUSE_MOVE: { break; } default : bHandled = CMenuBase::HandleMessage(pMessage); break; } } return bHandled;}void CMenu::UpdateCachedRects(void) const{ if (!m_bCachedRectsValid) { CRect SubRect(m_WindowRect); SubRect.Grow(-2); int iWidth = 5; for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter) { if (iter->first.bSpacer) { CRect TextRect(SubRect.Left() + iWidth, SubRect.Top() + 2, SubRect.Left() + iWidth + 1, SubRect.Bottom() - 2); TextRect.Grow(2); iter->second.second = TextRect;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -