2005-04-24 01:21:54 +02:00
|
|
|
/*
|
|
|
|
CDropDown
|
|
|
|
by Gustav Larsson
|
|
|
|
gee@pyro.nu
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precompiled.h"
|
|
|
|
#include "GUI.h"
|
|
|
|
#include "CDropDown.h"
|
|
|
|
|
|
|
|
#include "ogl.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
// Constructor / Destructor
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
CDropDown::CDropDown() : m_Open(false), m_HideScrollBar(false), m_ElementHighlight(-1)
|
|
|
|
{
|
2005-07-24 00:27:55 +02:00
|
|
|
AddSetting(GUIST_float, "button_width");
|
2005-04-24 01:21:54 +02:00
|
|
|
AddSetting(GUIST_float, "dropdown_size");
|
|
|
|
AddSetting(GUIST_float, "dropdown_buffer");
|
2005-07-24 00:27:55 +02:00
|
|
|
// AddSetting(GUIST_CStr, "font");
|
|
|
|
// AddSetting(GUIST_CGUISpriteInstance, "sprite"); // Background that sits around the size
|
2005-04-24 01:21:54 +02:00
|
|
|
AddSetting(GUIST_CGUISpriteInstance, "sprite_list"); // Background of the drop down list
|
|
|
|
AddSetting(GUIST_CGUISpriteInstance, "sprite2"); // Button that sits to the right
|
|
|
|
AddSetting(GUIST_CGUISpriteInstance, "sprite2_over");
|
|
|
|
AddSetting(GUIST_CGUISpriteInstance, "sprite2_pressed");
|
|
|
|
AddSetting(GUIST_CGUISpriteInstance, "sprite2_disabled");
|
|
|
|
AddSetting(GUIST_EVAlign, "text_valign");
|
2005-07-24 00:27:55 +02:00
|
|
|
|
|
|
|
// Add these in CList! And implement TODO
|
|
|
|
//AddSetting(GUIST_CColor, "textcolor_over");
|
|
|
|
//AddSetting(GUIST_CColor, "textcolor_pressed");
|
|
|
|
//AddSetting(GUIST_CColor, "textcolor_disabled");
|
2005-04-24 01:21:54 +02:00
|
|
|
|
|
|
|
// Scrollbar is forced to be true.
|
|
|
|
GUI<bool>::SetSetting(this, "scrollbar", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
CDropDown::~CDropDown()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDropDown::SetupText()
|
|
|
|
{
|
|
|
|
CList::SetupText();
|
|
|
|
|
|
|
|
SetupListRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDropDown::HandleMessage(const SGUIMessage &Message)
|
|
|
|
{
|
|
|
|
// Important
|
|
|
|
|
|
|
|
switch (Message.type)
|
|
|
|
{
|
|
|
|
case GUIM_SETTINGS_UPDATED:
|
|
|
|
bool scrollbar;
|
|
|
|
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
|
|
|
|
|
|
|
|
// Update scroll-bar
|
|
|
|
// TODO Gee: (2004-09-01) Is this really updated each time it should?
|
|
|
|
if (scrollbar &&
|
|
|
|
(Message.value == CStr("dropdown_size")/* ||
|
|
|
|
Message.value == CStr("")*/))
|
|
|
|
{
|
|
|
|
CRect rect = GetListRect();
|
|
|
|
GetScrollBar(0).SetX( rect.right );
|
|
|
|
GetScrollBar(0).SetY( rect.top );
|
|
|
|
GetScrollBar(0).SetZ( GetBufferedZ() );
|
|
|
|
GetScrollBar(0).SetLength( rect.bottom - rect.top );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update cached list rect
|
|
|
|
if (Message.value == CStr("size") ||
|
|
|
|
Message.value == CStr("absolute") ||
|
|
|
|
Message.value == CStr("dropdown_size") ||
|
|
|
|
Message.value == CStr("dropdown_buffer") ||
|
|
|
|
Message.value == CStr("scrollbar_style") ||
|
|
|
|
Message.value == CStr("button_width"))
|
|
|
|
{
|
|
|
|
SetupListRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GUIM_MOUSE_MOTION:{
|
|
|
|
if (m_Open)
|
|
|
|
{
|
|
|
|
CPos mouse = GetMousePos();
|
|
|
|
|
|
|
|
if (GetListRect().PointInside(mouse))
|
|
|
|
{
|
|
|
|
bool scrollbar;
|
|
|
|
CGUIList *pList;
|
|
|
|
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
|
|
|
|
GUI<CGUIList>::GetSettingPointer(this, "list", pList);
|
|
|
|
float scroll=0.f;
|
|
|
|
if (scrollbar)
|
|
|
|
{
|
|
|
|
scroll = GetScrollBar(0).GetPos();
|
|
|
|
}
|
|
|
|
|
|
|
|
CRect rect = GetListRect();
|
|
|
|
mouse.y += scroll;
|
|
|
|
int set=-1;
|
2005-04-26 22:28:36 +02:00
|
|
|
for (int i=0; i<(int)pList->m_Items.size(); ++i)
|
2005-04-24 01:21:54 +02:00
|
|
|
{
|
|
|
|
if (mouse.y >= rect.top + m_ItemsYPositions[i] &&
|
|
|
|
mouse.y < rect.top + m_ItemsYPositions[i+1] &&
|
|
|
|
// mouse is not over scroll-bar
|
|
|
|
!(mouse.x >= GetScrollBar(0).GetOuterRect().left &&
|
|
|
|
mouse.x <= GetScrollBar(0).GetOuterRect().right))
|
|
|
|
{
|
|
|
|
set = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (set != -1)
|
|
|
|
{
|
|
|
|
//GUI<int>::SetSetting(this, "selected", set);
|
|
|
|
m_ElementHighlight = set;
|
|
|
|
//UpdateAutoScroll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}break;
|
|
|
|
|
|
|
|
case GUIM_MOUSE_LEAVE:{
|
|
|
|
GUI<int>::GetSetting(this, "selected", m_ElementHighlight);
|
|
|
|
|
|
|
|
}break;
|
|
|
|
|
|
|
|
// We can't inherent this routine from CList, because we need to include
|
|
|
|
// a mouse click to open the dropdown, also the coordinates are changed.
|
|
|
|
case GUIM_MOUSE_PRESS_LEFT:
|
|
|
|
{
|
|
|
|
if (!m_Open)
|
|
|
|
{
|
|
|
|
m_Open = true;
|
|
|
|
GetScrollBar(0).SetPos(0.f);
|
|
|
|
UpdateAutoScroll();
|
|
|
|
GUI<int>::GetSetting(this, "selected", m_ElementHighlight);
|
|
|
|
return; // overshadow
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CPos mouse = GetMousePos();
|
|
|
|
|
|
|
|
// If the regular area is pressed, then abort, and close.
|
|
|
|
if (m_CachedActualSize.PointInside(mouse))
|
|
|
|
{
|
|
|
|
m_Open = false;
|
|
|
|
return; // overshadow
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(mouse.x >= GetScrollBar(0).GetOuterRect().left &&
|
|
|
|
mouse.x <= GetScrollBar(0).GetOuterRect().right) &&
|
|
|
|
mouse.y >= GetListRect().top)
|
|
|
|
{
|
|
|
|
m_Open = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case GUIM_LOST_FOCUS:
|
|
|
|
m_Open=false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GUIM_LOAD:
|
|
|
|
SetupListRect();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Important that this is after, so that overshadowed implementations aren't processed
|
|
|
|
CList::HandleMessage(Message);
|
|
|
|
}
|
|
|
|
|
2005-10-20 17:27:39 +02:00
|
|
|
InReaction CDropDown::ManuallyHandleEvent(const SDL_Event* ev)
|
2005-04-24 01:21:54 +02:00
|
|
|
{
|
|
|
|
int szChar = ev->key.keysym.sym;
|
|
|
|
bool update_highlight = false;
|
|
|
|
|
|
|
|
switch (szChar)
|
|
|
|
{
|
|
|
|
case '\r':
|
|
|
|
m_Open=false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SDLK_HOME:
|
|
|
|
case SDLK_END:
|
|
|
|
case SDLK_UP:
|
|
|
|
case SDLK_DOWN:
|
|
|
|
case SDLK_PAGEUP:
|
|
|
|
case SDLK_PAGEDOWN:
|
|
|
|
if (!m_Open)
|
2005-10-20 19:44:56 +02:00
|
|
|
return IN_PASS;
|
2005-04-24 01:21:54 +02:00
|
|
|
// Set current selected item to highlighted, before
|
|
|
|
// then really processing these in CList::ManuallyHandleEvent()
|
|
|
|
GUI<int>::SetSetting(this, "selected", m_ElementHighlight);
|
|
|
|
update_highlight = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
CList::ManuallyHandleEvent(ev);
|
|
|
|
|
|
|
|
if (update_highlight)
|
|
|
|
GUI<int>::GetSetting(this, "selected", m_ElementHighlight);
|
|
|
|
|
2005-10-20 19:44:56 +02:00
|
|
|
return IN_HANDLED;
|
2005-04-24 01:21:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CDropDown::SetupListRect()
|
|
|
|
{
|
|
|
|
float size, buffer, button_width;
|
|
|
|
GUI<float>::GetSetting(this, "dropdown_size", size);
|
|
|
|
GUI<float>::GetSetting(this, "dropdown_buffer", buffer);
|
|
|
|
GUI<float>::GetSetting(this, "button_width", button_width);
|
|
|
|
|
|
|
|
if (m_ItemsYPositions.empty() || m_ItemsYPositions.back() >= size)
|
|
|
|
{
|
|
|
|
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom+buffer,
|
|
|
|
m_CachedActualSize.right, m_CachedActualSize.bottom+buffer + size);
|
|
|
|
|
|
|
|
m_HideScrollBar = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_CachedListRect = CRect(m_CachedActualSize.left, m_CachedActualSize.bottom+buffer,
|
|
|
|
m_CachedActualSize.right - GetScrollBar(0).GetStyle()->m_Width, m_CachedActualSize.bottom+buffer + m_ItemsYPositions.back());
|
|
|
|
|
|
|
|
// We also need to hide the scrollbar
|
|
|
|
m_HideScrollBar = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CRect CDropDown::GetListRect() const
|
|
|
|
{
|
|
|
|
return m_CachedListRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CDropDown::MouseOver()
|
|
|
|
{
|
|
|
|
if(!GetGUI())
|
|
|
|
throw PS_NEEDS_PGUI;
|
|
|
|
|
|
|
|
if (m_Open)
|
|
|
|
{
|
|
|
|
CRect rect(m_CachedActualSize.left, m_CachedActualSize.top,
|
|
|
|
m_CachedActualSize.right, GetListRect().bottom);
|
|
|
|
|
|
|
|
|
|
|
|
return rect.PointInside(GetMousePos());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return m_CachedActualSize.PointInside(GetMousePos());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDropDown::Draw()
|
|
|
|
{
|
|
|
|
if (!GetGUI())
|
|
|
|
return;
|
|
|
|
|
|
|
|
float bz = GetBufferedZ();
|
|
|
|
|
|
|
|
float dropdown_size, button_width;
|
|
|
|
GUI<float>::GetSetting(this, "dropdown_size", dropdown_size);
|
|
|
|
GUI<float>::GetSetting(this, "button_width", button_width);
|
|
|
|
|
|
|
|
CGUISpriteInstance *sprite, *sprite2, *sprite2_second;
|
|
|
|
int cell_id, selected=0;
|
|
|
|
CColor color;
|
|
|
|
|
|
|
|
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite", sprite);
|
|
|
|
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite2", sprite2);
|
|
|
|
GUI<int>::GetSetting(this, "cell_id", cell_id);
|
|
|
|
GUI<int>::GetSetting(this, "selected", selected);
|
|
|
|
GUI<CColor>::GetSetting(this, "textcolor", color);
|
|
|
|
|
|
|
|
|
|
|
|
bool enabled;
|
|
|
|
GUI<bool>::GetSetting(this, "enabled", enabled);
|
|
|
|
|
|
|
|
GetGUI()->DrawSprite(*sprite, cell_id, bz, m_CachedActualSize);
|
|
|
|
|
|
|
|
if (button_width > 0.f)
|
|
|
|
{
|
|
|
|
CRect rect(m_CachedActualSize.right-button_width, m_CachedActualSize.top,
|
|
|
|
m_CachedActualSize.right, m_CachedActualSize.bottom);
|
|
|
|
|
|
|
|
if (!enabled)
|
|
|
|
{
|
|
|
|
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite2_disabled", sprite2_second);
|
|
|
|
GetGUI()->DrawSprite(GUI<>::FallBackSprite(*sprite2_second, *sprite2), cell_id, bz+0.05f, rect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (m_Open)
|
|
|
|
{
|
|
|
|
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite2_pressed", sprite2_second);
|
|
|
|
GetGUI()->DrawSprite(GUI<>::FallBackSprite(*sprite2_second, *sprite2), cell_id, bz+0.05f, rect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (m_MouseHovering)
|
|
|
|
{
|
|
|
|
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite2_over", sprite2_second);
|
|
|
|
GetGUI()->DrawSprite(GUI<>::FallBackSprite(*sprite2_second, *sprite2), cell_id, bz+0.05f, rect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
GetGUI()->DrawSprite(*sprite2, cell_id, bz+0.05f, rect);
|
|
|
|
}
|
|
|
|
|
2005-07-24 00:27:55 +02:00
|
|
|
if (selected != -1) // TODO: Maybe check validity completely?
|
|
|
|
{
|
2005-07-24 10:29:02 +02:00
|
|
|
// figure out clipping rectangle
|
|
|
|
CRect cliparea(m_CachedActualSize.left, m_CachedActualSize.top,
|
|
|
|
m_CachedActualSize.right-button_width, m_CachedActualSize.bottom);
|
|
|
|
|
2005-07-24 00:27:55 +02:00
|
|
|
CPos pos(m_CachedActualSize.left, m_CachedActualSize.top);
|
2005-07-24 10:29:02 +02:00
|
|
|
IGUITextOwner::Draw(selected, color, pos, bz+0.1f, cliparea);
|
2005-07-24 00:27:55 +02:00
|
|
|
}
|
2005-04-24 01:21:54 +02:00
|
|
|
|
|
|
|
bool *scrollbar=NULL, old;
|
|
|
|
GUI<bool>::GetSettingPointer(this, "scrollbar", scrollbar);
|
|
|
|
|
|
|
|
old = *scrollbar;
|
|
|
|
|
|
|
|
if (m_Open)
|
|
|
|
{
|
|
|
|
if (m_HideScrollBar)
|
|
|
|
*scrollbar = false;
|
|
|
|
|
|
|
|
DrawList(m_ElementHighlight, "sprite_list", "sprite_selectarea", "textcolor");
|
|
|
|
|
|
|
|
if (m_HideScrollBar)
|
|
|
|
*scrollbar = old;
|
|
|
|
}
|
|
|
|
}
|