00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "wgui_include_config.h"
00026 #include "wg_menu.h"
00027 #include "std_ex.h"
00028 #include "wg_application.h"
00029 #include "wg_message_server.h"
00030 #include "wg_view.h"
00031 #include "wutil_debug.h"
00032 #include "wg_error.h"
00033
00034
00035 namespace wGui
00036 {
00037
00038
00039
00040 CMenuBase::CMenuBase(const CRect& WindowRect, CWindow* pParent, CFontEngine* pFontEngine) :
00041 CWindow(WindowRect, pParent),
00042 m_pHighlightedItem(0),
00043 m_bCachedRectsValid(false),
00044 m_pActivePopup(0),
00045 m_hRightArrowBitmap(WGRES_RIGHT_ARROW_BITMAP),
00046 m_HighlightColor(DEFAULT_BACKGROUND_COLOR),
00047 m_pPopupTimer(0)
00048 {
00049 if (pFontEngine)
00050 {
00051 m_pFontEngine = pFontEngine;
00052 }
00053 else
00054 {
00055 m_pFontEngine = CApplication::Instance()->GetDefaultFontEngine();
00056 }
00057
00058 m_HighlightColor = CApplication::Instance()->GetDefaultSelectionColor();
00059
00060 CMessageServer::Instance().RegisterMessageClient(this, CMessage::MOUSE_MOVE);
00061 CMessageServer::Instance().RegisterMessageClient(this, CMessage::CTRL_SINGLELCLICK);
00062 CMessageServer::Instance().RegisterMessageClient(this, CMessage::CTRL_TIMER);
00063
00064 m_pPopupTimer = new CTimer(this);
00065 }
00066
00067
00068 CMenuBase::~CMenuBase(void)
00069 {
00070 delete m_pPopupTimer;
00071 m_pPopupTimer = 0;
00072 }
00073
00074
00075 void CMenuBase::InsertMenuItem(const SMenuItem& MenuItem, int iPosition)
00076 {
00077 m_MenuItems.insert((iPosition == -1) ? m_MenuItems.end() : m_MenuItems.begin() + iPosition,
00078 s_MenuItemInfo(MenuItem, CRenderedString(m_pFontEngine, MenuItem.sItemText, CRenderedString::VALIGN_TOP), CRect()));
00079 m_bCachedRectsValid = false;
00080
00081 }
00082
00083
00084 void CMenuBase::RemoveMenuItem(int iPosition)
00085 {
00086 m_MenuItems.erase(m_MenuItems.begin() + iPosition);
00087 m_bCachedRectsValid = false;
00088 Draw();
00089 }
00090
00091
00092 void CMenuBase::HideActivePopup(void)
00093 {
00094 if (m_pActivePopup)
00095 {
00096 m_pActivePopup->Hide();
00097 m_pActivePopup = 0;
00098 }
00099 }
00100
00101
00102 bool CMenuBase::OnMouseButtonDown(CPoint Point, unsigned int Button)
00103 {
00104
00105 bool bResult = false;
00106
00107 if (m_bVisible)
00108 {
00109 for (std::list<CWindow*>::reverse_iterator iter = m_ChildWindows.rbegin(); iter != m_ChildWindows.rend(); ++iter)
00110 {
00111 bResult = (*iter)->OnMouseButtonDown(Point, Button);
00112 if (bResult)
00113 {
00114 break;
00115 }
00116 }
00117 }
00118
00119 return bResult;
00120 }
00121
00122
00123 bool CMenuBase::HandleMessage(CMessage* pMessage)
00124 {
00125 bool bHandled = false;
00126
00127 if (pMessage)
00128 {
00129 switch(pMessage->MessageType())
00130 {
00131 case CMessage::MOUSE_MOVE:
00132 {
00133 CMouseMessage* pMouseMessage = dynamic_cast<CMouseMessage*>(pMessage);
00134 if (m_bVisible && pMouseMessage &&
00135 m_WindowRect.SizeRect().HitTest(ViewToWindow(pMouseMessage->Point)) == CRect::RELPOS_INSIDE)
00136 {
00137 UpdateCachedRects();
00138 SMenuItem* pOldHighlight = m_pHighlightedItem;
00139 m_pHighlightedItem = 0;
00140 CPoint WindowPoint(ViewToWindow(pMouseMessage->Point));
00141 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00142 {
00143 if (iter->Rect.HitTest(WindowPoint) == CRect::RELPOS_INSIDE && !iter->MenuItem.bSpacer)
00144 {
00145 m_pHighlightedItem = &(iter->MenuItem);
00146 break;
00147 }
00148 }
00149 if (pOldHighlight != m_pHighlightedItem)
00150 {
00151 m_pPopupTimer->StopTimer();
00152 if (m_pHighlightedItem && m_pHighlightedItem->pPopup)
00153 {
00154 m_pPopupTimer->StartTimer(1000);
00155 }
00156 Draw();
00157 }
00158 }
00159 else if (m_pHighlightedItem != 0)
00160 {
00161 m_pPopupTimer->StopTimer();
00162 m_pHighlightedItem = 0;
00163 Draw();
00164 }
00165 break;
00166 }
00167 case CMessage::CTRL_SINGLELCLICK:
00168 {
00169 TIntMessage* pCtrlMessage = dynamic_cast<TIntMessage*>(pMessage);
00170 if (pCtrlMessage && pCtrlMessage->Destination() == this)
00171 {
00172 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00173 {
00174 if (pCtrlMessage->Source() == iter->MenuItem.pPopup)
00175 {
00176 CMessageServer::Instance().QueueMessage(new TIntMessage(CMessage::CTRL_SINGLELCLICK, m_pParentWindow,
00177 this, pCtrlMessage->Value()));
00178 bHandled = true;
00179 break;
00180 }
00181 }
00182 }
00183 break;
00184 }
00185 case CMessage::CTRL_TIMER:
00186 {
00187 if (pMessage->Destination() == this)
00188 {
00189 bHandled = true;
00190 }
00191 break;
00192 }
00193 default :
00194 bHandled = CWindow::HandleMessage(pMessage);
00195 break;
00196 }
00197 }
00198
00199 return bHandled;
00200 }
00201
00202
00203
00204
00205 CMenu::CMenu(const CRect& WindowRect, CWindow* pParent, CFontEngine* pFontEngine) :
00206 CMenuBase(WindowRect, pParent, pFontEngine)
00207 {
00208 CMessageServer::Instance().RegisterMessageClient(this, CMessage::MOUSE_MOVE);
00209 Draw();
00210 }
00211
00212
00213 CMenu::~CMenu(void)
00214 {
00215
00216 }
00217
00218
00219 void CMenu::InsertMenuItem(const SMenuItem& MenuItem, int iPosition)
00220 {
00221 m_MenuItems.insert((iPosition == -1) ? m_MenuItems.end() : m_MenuItems.begin() + iPosition,
00222 s_MenuItemInfo(MenuItem, CRenderedString(m_pFontEngine, MenuItem.sItemText, CRenderedString::VALIGN_NORMAL), CRect()));
00223 m_bCachedRectsValid = false;
00224 if (MenuItem.pPopup)
00225 {
00226 MenuItem.pPopup->SetParentMenu(this);
00227 }
00228 Draw();
00229 }
00230
00231
00232 void CMenu::Draw(void) const
00233 {
00234 CWindow::Draw();
00235
00236 if (m_pSDLSurface)
00237 {
00238 CPainter Painter(m_pSDLSurface, CPainter::PAINT_REPLACE);
00239 UpdateCachedRects();
00240 for (t_MenuItemVector::const_iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00241 {
00242 if (m_pHighlightedItem == &(iter->MenuItem))
00243 {
00244 Painter.DrawRect(iter->Rect, true, m_HighlightColor, m_HighlightColor);
00245 }
00246 CRect TextRect(iter->Rect);
00247 TextRect.Grow(-2);
00248 if (iter->MenuItem.bSpacer)
00249 {
00250 Painter.DrawVLine(TextRect.Top(), TextRect.Bottom(), TextRect.Left(), COLOR_LIGHTGRAY);
00251 Painter.DrawVLine(TextRect.Top(), TextRect.Bottom(), TextRect.Right(), COLOR_DARKGRAY);
00252 }
00253 else
00254 iter->RenderedString.Draw(m_pSDLSurface, TextRect, CPoint(TextRect.Left(), (TextRect.Top() + TextRect.Bottom()) * 3 / 4));
00255 }
00256 }
00257 }
00258
00259
00260 bool CMenu::OnMouseButtonDown(CPoint Point, unsigned int Button)
00261 {
00262 bool bResult = CMenuBase::OnMouseButtonDown(Point, Button);
00263
00264 if (!bResult && m_bVisible && (Button == CMouseMessage::LEFT) &&
00265 (m_WindowRect.SizeRect().HitTest(ViewToWindow(Point)) == CRect::RELPOS_INSIDE))
00266 {
00267 UpdateCachedRects();
00268 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00269 {
00270 if (iter->Rect.HitTest(ViewToWindow(Point)) == CRect::RELPOS_INSIDE && !iter->MenuItem.bSpacer)
00271 {
00272 HideActivePopup();
00273 if (iter->MenuItem.pPopup)
00274 {
00275 CPopupMenu* pPopup = dynamic_cast<CPopupMenu*>(iter->MenuItem.pPopup);
00276 if (pPopup)
00277 {
00278 m_pActivePopup = pPopup;
00279 ShowActivePopup(iter->Rect, GetAncestor(ROOT)->GetClientRect());
00280 }
00281 }
00282 else
00283 {
00284 CMessageServer::Instance().QueueMessage(new TIntMessage(CMessage::CTRL_SINGLELCLICK, m_pParentWindow, this, iter->MenuItem.iItemId));
00285 }
00286 break;
00287 }
00288 }
00289 bResult = true;
00290 }
00291
00292 return bResult;
00293 }
00294
00295
00296 bool CMenu::HandleMessage(CMessage* pMessage)
00297 {
00298 bool bHandled = false;
00299
00300 if (pMessage)
00301 {
00302 switch(pMessage->MessageType())
00303 {
00304 case CMessage::MOUSE_MOVE:
00305 {
00306 CMouseMessage* pMouseMessage = dynamic_cast<CMouseMessage*>(pMessage);
00307 if (m_bVisible && pMouseMessage &&
00308 m_WindowRect.SizeRect().HitTest(ViewToWindow(pMouseMessage->Point)) == CRect::RELPOS_INSIDE)
00309 {
00310 UpdateCachedRects();
00311 SMenuItem* pOldHighlight = m_pHighlightedItem;
00312 m_pHighlightedItem = 0;
00313 CPoint WindowPoint(ViewToWindow(pMouseMessage->Point));
00314 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00315 {
00316 if (iter->Rect.HitTest(WindowPoint) == CRect::RELPOS_INSIDE && !iter->MenuItem.bSpacer)
00317 {
00318 m_pHighlightedItem = &(iter->MenuItem);
00319 break;
00320 }
00321 }
00322 if (pOldHighlight != m_pHighlightedItem)
00323 {
00324 Draw();
00325 }
00326 }
00327 else if (m_pHighlightedItem != 0)
00328 {
00329 m_pHighlightedItem = 0;
00330 Draw();
00331 }
00332 break;
00333 }
00334 default :
00335 bHandled = CMenuBase::HandleMessage(pMessage);
00336 break;
00337 }
00338 }
00339
00340 return bHandled;
00341 }
00342
00343
00344 void CMenu::UpdateCachedRects(void) const
00345 {
00346 if (!m_bCachedRectsValid)
00347 {
00348 CRect SubRect(m_WindowRect.SizeRect());
00349 SubRect.Grow(-2);
00350 int iWidth = 5;
00351 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00352 {
00353 if (iter->MenuItem.bSpacer)
00354 {
00355 CRect TextRect(SubRect.Left() + iWidth, SubRect.Top() + 2, SubRect.Left() + iWidth + 1, SubRect.Bottom() - 2);
00356 TextRect.Grow(2);
00357 iter->Rect = TextRect;
00358 iWidth += 9;
00359 }
00360 else
00361 {
00362 CPoint Dims;
00363 iter->RenderedString.GetMetrics(&Dims, 0, 0);
00364 CRect TextRect(SubRect.Left() + iWidth, SubRect.Top() + 2, SubRect.Left() + iWidth + Dims.XPos(), SubRect.Bottom() - 2);
00365 TextRect.Grow(2);
00366 iter->Rect = TextRect;
00367 iWidth += Dims.XPos() + 8;
00368 }
00369 }
00370 m_bCachedRectsValid = true;
00371 }
00372 }
00373
00374
00375 void CMenu::ShowActivePopup(const CRect& ParentRect, const CRect& BoundingRect)
00376 {
00377
00378 if (!m_pActivePopup)
00379 {
00380 throw(Wg_Ex_App(L"CMenu::ShowActivePopup() : Trying to show active popup menu when pActivePopup is NULL!"));
00381 }
00382 CRect MenuRect = m_pActivePopup->GetWindowRect();
00383 if (BoundingRect.HitTest(ParentRect.BottomLeft() + CPoint(MenuRect.Width(), 0)) & CRect::RELPOS_RIGHT)
00384 {
00385 int xDelta = BoundingRect.Right() - ParentRect.Left() + MenuRect.Width();
00386 if (!(BoundingRect.HitTest(ParentRect.BottomLeft() + CPoint(xDelta, 0)) & CRect::RELPOS_LEFT))
00387 {
00388 m_pActivePopup->Show(ParentRect.BottomLeft() + CPoint(xDelta, 5));
00389 }
00390 }
00391 else
00392 {
00393 m_pActivePopup->Show(ParentRect.BottomLeft() + CPoint(0, 5));
00394 }
00395
00396 m_pActivePopup->SetNewParent(m_pActivePopup->GetAncestor(PARENT));
00397 }
00398
00399
00400
00401
00402 CPopupMenu::CPopupMenu(const CRect& WindowRect, CWindow* pParent, CFontEngine* pFontEngine) :
00403 CMenuBase(WindowRect, pParent, pFontEngine),
00404 m_pParentMenu(0)
00405 {
00406 m_bVisible = false;
00407 CMessageServer::Instance().RegisterMessageClient(this, CMessage::MOUSE_BUTTONDOWN);
00408 Draw();
00409 }
00410
00411
00412 CPopupMenu::~CPopupMenu(void)
00413 {
00414
00415 }
00416
00417
00418 void CPopupMenu::Show(CPoint Position)
00419 {
00420 if (m_bVisible)
00421 {
00422 Hide();
00423 }
00424
00425 int iHeight = 4;
00426 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00427 {
00428 if (iter->MenuItem.bSpacer)
00429 iHeight += 6;
00430 else
00431 {
00432 CPoint Dims;
00433 iter->RenderedString.GetMetrics(&Dims, 0, 0);
00434 iHeight += Dims.YPos() + 5;
00435 }
00436 }
00437
00438
00439 CRect TestRect = GetAncestor(ROOT)->GetWindowRect();
00440
00441 if ( Position.XPos() < 0 )
00442 {
00443 Position.SetX(0);
00444 }
00445
00446 if ( Position.YPos() < 0 )
00447 {
00448 Position.SetY(0);
00449 }
00450
00451 if ( Position.XPos() + m_WindowRect.Width() > TestRect.Width() )
00452 {
00453 Position.SetX(Position.XPos() - ((Position.XPos() + m_WindowRect.Width()) - TestRect.Width()));
00454 }
00455
00456 if ( Position.YPos() + m_WindowRect.Height() > TestRect.Height() )
00457 {
00458 Position.SetY(Position.YPos() - ((Position.YPos() + m_WindowRect.Height()) - TestRect.Bottom()));
00459 }
00460
00461 SetWindowRect(GetAncestor(PARENT)->ViewToClient(CRect(Position, Position + CPoint(m_WindowRect.Width() - 1, iHeight + 2))));
00462 m_bVisible = true;
00463 CView* pView = GetView();
00464 if (pView && !dynamic_cast<CPopupMenu*>(m_pParentWindow))
00465 {
00466 pView->SetFloatingWindow(this);
00467 }
00468 Draw();
00469 }
00470
00471
00472 void CPopupMenu::Hide(void)
00473 {
00474 HideActivePopup();
00475 m_bVisible = false;
00476 m_bCachedRectsValid = false;
00477 CView* pView = GetView();
00478 if (!dynamic_cast<CPopupMenu*>(m_pParentWindow) && pView && pView->GetFloatingWindow() == this)
00479 {
00480 pView->SetFloatingWindow(0);
00481 }
00482 CMessageServer::Instance().QueueMessage(new CMessage(CMessage::APP_PAINT, 0, this));
00483 m_pHighlightedItem = 0;
00484 Draw();
00485 }
00486
00487
00488 void CPopupMenu::HideAll(void)
00489 {
00490 CPopupMenu* pParentPopup = dynamic_cast<CPopupMenu*>(m_pParentWindow);
00491 if (pParentPopup)
00492 {
00493 pParentPopup->HideAll();
00494 }
00495 else
00496 {
00497 CMenu* pRootMenu = dynamic_cast<CMenu*>(m_pParentWindow);
00498 if (pRootMenu)
00499 {
00500 pRootMenu->HideActivePopup();
00501 }
00502 else
00503 {
00504 Hide();
00505 }
00506 }
00507 }
00508
00509
00510 bool CPopupMenu::IsInsideChild(const CPoint& Point) const
00511 {
00512 if (m_WindowRect.SizeRect().HitTest(ViewToWindow(Point)) == CRect::RELPOS_INSIDE)
00513 {
00514 return true;
00515 }
00516 if (!m_pActivePopup)
00517 {
00518 return false;
00519 }
00520 return m_pActivePopup->IsInsideChild(Point);
00521 }
00522
00523
00524 void CPopupMenu::Draw(void) const
00525 {
00526 CWindow::Draw();
00527
00528 if (m_pSDLSurface)
00529 {
00530 CPainter Painter(m_pSDLSurface, CPainter::PAINT_REPLACE);
00531 Painter.DrawRect(m_WindowRect.SizeRect(), false, COLOR_LIGHTGRAY);
00532 Painter.DrawHLine(0, m_WindowRect.Width(), m_WindowRect.Height(), COLOR_DARKGRAY);
00533 Painter.DrawVLine(0, m_WindowRect.Height(), m_WindowRect.Width(), COLOR_DARKGRAY);
00534 UpdateCachedRects();
00535 for (t_MenuItemVector::const_iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00536 {
00537 if (m_pHighlightedItem == &(iter->MenuItem))
00538 {
00539 Painter.DrawRect(iter->Rect, true, m_HighlightColor, m_HighlightColor);
00540 }
00541 CRect TextRect(iter->Rect);
00542 TextRect.Grow(-2);
00543 if (iter->MenuItem.bSpacer)
00544 {
00545 Painter.DrawHLine(TextRect.Left(), TextRect.Right(), TextRect.Top(), COLOR_LIGHTGRAY);
00546 Painter.DrawHLine(TextRect.Left(), TextRect.Right(), TextRect.Bottom(), COLOR_DARKGRAY);
00547 }
00548 else
00549 iter->RenderedString.Draw(m_pSDLSurface, TextRect, TextRect.TopLeft());
00550 if (iter->MenuItem.pPopup)
00551 {
00552 CRect ArrowRect(iter->Rect);
00553 ArrowRect.SetLeft(ArrowRect.Right() - m_hRightArrowBitmap.Bitmap()->w);
00554 SDL_Rect SourceRect;
00555 SourceRect.x = stdex::safe_static_cast<short int>(0);
00556 SourceRect.y = stdex::safe_static_cast<short int>((m_hRightArrowBitmap.Bitmap()->h - ArrowRect.Height()) / 2 < 0 ?
00557 0 : (m_hRightArrowBitmap.Bitmap()->h - ArrowRect.Height()) / 2);
00558 SourceRect.w = stdex::safe_static_cast<short int>(m_hRightArrowBitmap.Bitmap()->w);
00559 SourceRect.h = stdex::safe_static_cast<short int>(std::min(ArrowRect.Height(), m_hRightArrowBitmap.Bitmap()->h));
00560 SDL_Rect DestRect;
00561 DestRect.x = stdex::safe_static_cast<short int>(ArrowRect.Left());
00562 DestRect.y = stdex::safe_static_cast<short int>((ArrowRect.Height() - m_hRightArrowBitmap.Bitmap()->h) / 2 < 0 ?
00563 ArrowRect.Top() : ArrowRect.Top() + (ArrowRect.Height() - m_hRightArrowBitmap.Bitmap()->h) / 2);
00564 DestRect.w = stdex::safe_static_cast<short int>(m_hRightArrowBitmap.Bitmap()->w);
00565 DestRect.h = stdex::safe_static_cast<short int>(std::min(ArrowRect.Height(), m_hRightArrowBitmap.Bitmap()->h));
00566 SDL_BlitSurface(m_hRightArrowBitmap.Bitmap(), &SourceRect, m_pSDLSurface, &DestRect);
00567 }
00568 }
00569 }
00570 }
00571
00572
00573 void CPopupMenu::PaintToSurface(SDL_Surface& , SDL_Surface& FloatingSurface, const CPoint& Offset) const
00574 {
00575 if (m_bVisible)
00576 {
00577 SDL_Rect SourceRect = CRect(m_WindowRect.SizeRect()).SDLRect();
00578 SDL_Rect DestRect = CRect(m_WindowRect + Offset).SDLRect();
00579 SDL_BlitSurface(m_pSDLSurface, &SourceRect, &FloatingSurface, &DestRect);
00580 CPoint NewOffset = m_ClientRect.TopLeft() + m_WindowRect.TopLeft() + Offset;
00581 for (std::list<CWindow*>::const_iterator iter = m_ChildWindows.begin(); iter != m_ChildWindows.end(); ++iter)
00582 {
00583 (*iter)->PaintToSurface(FloatingSurface, FloatingSurface, NewOffset);
00584 }
00585 }
00586 }
00587
00588
00589 bool CPopupMenu::OnMouseButtonDown(CPoint Point, unsigned int Button)
00590 {
00591 bool bResult = CMenuBase::OnMouseButtonDown(Point, Button);
00592
00593 CPoint WindowPoint(ViewToWindow(Point));
00594 if (!bResult && m_bVisible && (m_WindowRect.SizeRect().HitTest(WindowPoint) == CRect::RELPOS_INSIDE))
00595 {
00596 UpdateCachedRects();
00597 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00598 {
00599 if (iter->Rect.HitTest(WindowPoint) == CRect::RELPOS_INSIDE && !iter->MenuItem.bSpacer)
00600 {
00601 if (!iter->MenuItem.pPopup)
00602 {
00603 CMessageClient* pDestination = m_pParentWindow;
00604 if (m_pParentMenu)
00605 {
00606 pDestination = m_pParentMenu;
00607 }
00608 CMessageServer::Instance().QueueMessage(new TIntMessage(CMessage::CTRL_SINGLELCLICK, pDestination, this, iter->MenuItem.iItemId));
00609 HideAll();
00610 }
00611 else
00612 {
00613 HideActivePopup();
00614 m_pActivePopup = iter->MenuItem.pPopup;
00615 ShowActivePopup(iter->Rect, GetAncestor(ROOT)->GetClientRect());
00616 }
00617 break;
00618 }
00619 }
00620 bResult = true;
00621 }
00622
00623 return bResult;
00624 }
00625
00626
00627 bool CPopupMenu::HandleMessage(CMessage* pMessage)
00628 {
00629 bool bHandled = false;
00630
00631 if (pMessage)
00632 {
00633 switch(pMessage->MessageType())
00634 {
00635 case CMessage::MOUSE_BUTTONDOWN:
00636 {
00637 CMouseMessage* pMouseMessage = dynamic_cast<CMouseMessage*>(pMessage);
00638 if (m_bVisible && pMouseMessage &&
00639 m_WindowRect.SizeRect().HitTest(ViewToWindow(pMouseMessage->Point)) != CRect::RELPOS_INSIDE)
00640 {
00641
00642
00643
00644 if (!dynamic_cast<CPopupMenu*>(m_pParentWindow) && !IsInsideChild(pMouseMessage->Point) &&
00645 !(m_pParentMenu && m_pParentMenu->GetWindowRect().SizeRect().HitTest(
00646 m_pParentMenu->ViewToWindow(pMouseMessage->Point)) == CRect::RELPOS_INSIDE))
00647 {
00648 HideAll();
00649 }
00650 }
00651 break;
00652 }
00653 case CMessage::CTRL_TIMER:
00654 {
00655 if (pMessage->Destination() == this)
00656 {
00657 CRect ItemRect;
00658 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00659 {
00660 if (m_pHighlightedItem == &(iter->MenuItem))
00661 {
00662 ItemRect = iter->Rect;
00663 break;
00664 }
00665 }
00666 if (m_pHighlightedItem && m_pHighlightedItem->pPopup)
00667 {
00668 HideActivePopup();
00669 m_pActivePopup = m_pHighlightedItem->pPopup;
00670 ShowActivePopup(ItemRect, GetAncestor(ROOT)->GetClientRect());
00671 }
00672 bHandled = true;
00673 }
00674 break;
00675 }
00676 default :
00677 bHandled = CMenuBase::HandleMessage(pMessage);
00678 break;
00679 }
00680 }
00681
00682 return bHandled;
00683 }
00684
00685
00686 void CPopupMenu::UpdateCachedRects(void) const
00687 {
00688 if (!m_bCachedRectsValid)
00689 {
00690 CRect SubRect(m_WindowRect.SizeRect());
00691 SubRect.Grow(-2);
00692 int iHeight = 4;
00693 for (t_MenuItemVector::iterator iter = m_MenuItems.begin(); iter != m_MenuItems.end(); ++iter)
00694 {
00695 if (iter->MenuItem.bSpacer)
00696 {
00697 CRect TextRect(SubRect.Left() + 3, SubRect.Top() + iHeight, SubRect.Right() - 3, SubRect.Top() + iHeight + 1);
00698 TextRect.Grow(2);
00699 iter->Rect = TextRect;
00700 iHeight += 6;
00701 }
00702 else
00703 {
00704 CPoint Dims;
00705 iter->RenderedString.GetMetrics(&Dims, 0, 0);
00706 CRect TextRect(SubRect.Left() + 3, SubRect.Top() + iHeight, SubRect.Right() - 3, SubRect.Top() + iHeight + Dims.YPos());
00707 TextRect.Grow(2);
00708 iter->Rect = TextRect;
00709 iHeight += Dims.YPos() + 5;
00710 }
00711 }
00712 m_bCachedRectsValid = true;
00713 }
00714 }
00715
00716
00717 void CPopupMenu::ShowActivePopup(const CRect& ParentRect, const CRect& BoundingRect)
00718 {
00719
00720 if (!m_pActivePopup)
00721 {
00722 throw(Wg_Ex_App(L"CPopupMenu::ShowActivePopup() : Trying to show active popup menu when pActivePopup is NULL!"));
00723 }
00724
00725 CRect MenuRect = m_pActivePopup->GetWindowRect();
00726
00727
00728 if (BoundingRect.HitTest(ParentRect.TopRight() + CPoint(5, 0) + CPoint(MenuRect.Width(), 0)) & CRect::RELPOS_RIGHT)
00729 {
00730 m_pActivePopup->Show(ClientToView(ParentRect.TopLeft() - CPoint(MenuRect.Width() + 5, 0)) - m_ClientRect.TopLeft());
00731 }
00732 else
00733 {
00734 m_pActivePopup->Show(ClientToView(ParentRect.TopRight() + CPoint(5, 0)) - m_ClientRect.TopLeft());
00735 }
00736 }
00737
00738 }