If you have comments or questions concerning this source file, discuss them in the forum.
/*
Copyright (c) 2002 Nicolai Haehnle
See the license.txt for details. If that file was not included in the
source distributions, please email <prefect@rtts.org>
*/
// gui_popupmenu.cpp -- popup-menu specialization
#include "library.h"
#include "hal.h"
#include "gui_popupmenu.h"
/*
==============================================================================
GPopupMenu IMPLEMENTATION
==============================================================================
*/
/*
===============
GPopupMenu::GPopupMenu
Initialize a popup menu
===============
*/
GPopupMenu::GPopupMenu()
: GMenu(0, 0, 0, 0, 0)
{
SetCanFocus(true);
SetVisible(false);
SetTopLevel(true);
}
/*
===============
GPopupMenu::~GPopupMenu
Cleanup menu data
===============
*/
GPopupMenu::~GPopupMenu()
{
}
/*
===============
GPopupMenu::Display
Display the menu at the given location. The menu can be moved to make sure it
fits onto the screen.
===============
*/
void GPopupMenu::Display(int x, int y)
{
int w, h;
// set size
w = 0;
h = 0;
for(GMenuItem::v_it item = m_MenuItems.begin(); item != m_MenuItems.end(); item++) {
if ((*item)->GetWidth() > w)
w = (*item)->GetWidth();
h += (*item)->GetHeight();
}
SetSize(w, h);
// set position
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (x+w > 640)
x = 640-w;
if (y+h > 480)
y = 480-h;
SetPos(x, y);
// run the whole thing
SetVisible(true);
m_iHighlighted = -1;
int code = Run();
SetVisible(false);
if (code >= 0 && code < m_MenuItems.size()) {
GMenuItem *pItem = m_MenuItems[code];
pItem->signaled.Emit();
}
}
/*
===============
GPopupMenu::DisplayNearMouse
Convenience function that will display the menu near the mouse (useful for
context menus)
===============
*/
void GPopupMenu::DisplayNearMouse()
{
int mx, my;
hal->GetMouseState(&mx, &my);
Display(mx, my);
}
/*
===============
GPopupMenu::Begin
Grab the mouse when we get modal. This way, we get mouse-click even outside
the menu.
If a hierarchy of popupmenus is running, then the topmost menu should be
modal and own the mousegrab.
===============
*/
void GPopupMenu::Begin()
{
GrabMouse(true);
}
void GPopupMenu::End()
{
GrabMouse(false);
}
/*
===============
GPopupMenu::Draw
Draw all the menu items
===============
*/
void GPopupMenu::Draw()
{
hal->FillRect(0, 0, m_rc.size[0], m_rc.size[1], 0, 0, 0, 200);
int y = 0;
for(GMenuItem::v_it item = m_MenuItems.begin(); item != m_MenuItems.end(); item++) {
(*item)->Draw(0, y, (item-m_MenuItems.begin()) == m_iHighlighted);
y += (*item)->GetHeight();
}
}
/*
===============
GPopupMenu::MouseButton
Left-click activates the currently highlighted item and quits the menu
===============
*/
bool GPopupMenu::MouseButton(int btn, int x, int y, bool down)
{
if (!IsMouseOver()) {
EndModal(-1);
return true;
}
TrackMouse(x, y);
if (btn == 0)
{
if (!down && m_iHighlighted >= 0)
EndModal(m_iHighlighted);
return true;
}
return false;
}
/*
===============
GPopupMenu::MouseMove
Track the highlight
===============
*/
void GPopupMenu::MouseMove(int x, int y)
{
TrackMouse(x, y);
}
/*
===============
GPopupMenu::TrackMouse
Set the highlight depending on the current mouse pos
===============
*/
void GPopupMenu::TrackMouse(int x, int y)
{
if (x >= 0 && x < m_rc.size[0] && y >= 0 && y < m_rc.size[0])
{
int h = 0;
for(GMenuItem::v_it item = m_MenuItems.begin(); item != m_MenuItems.end(); item++) {
h += (*item)->GetHeight();
if (y < h) {
m_iHighlighted = item - m_MenuItems.begin();
return;
}
}
}
m_iHighlighted = -1;
}