forked from 0ad/0ad
CDropDown and the CGUIList type. This code is kind of rough around the edges as of yet. I'll work on it more.
This was SVN commit r2164.
This commit is contained in:
parent
15759ff4d7
commit
15f951bfbc
337
source/gui/CDropDown.cpp
Normal file
337
source/gui/CDropDown.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
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)
|
||||
{
|
||||
AddSetting(GUIST_float, "dropdown_size");
|
||||
AddSetting(GUIST_float, "dropdown_buffer");
|
||||
AddSetting(GUIST_CStr, "font");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite"); // Background that sits around the size
|
||||
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_float, "button_width");
|
||||
AddSetting(GUIST_EVAlign, "text_valign");
|
||||
AddSetting(GUIST_CColor, "textcolor_over");
|
||||
AddSetting(GUIST_CColor, "textcolor_pressed");
|
||||
AddSetting(GUIST_CColor, "textcolor_disabled");
|
||||
|
||||
// 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;
|
||||
for (int i=0; i<pList->m_Items.size(); ++i)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
int CDropDown::ManuallyHandleEvent(const SDL_Event* ev)
|
||||
{
|
||||
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)
|
||||
return EV_PASS;
|
||||
// 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);
|
||||
|
||||
return EV_HANDLED;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
CPos pos(m_CachedActualSize.left, m_CachedActualSize.top);
|
||||
IGUITextOwner::Draw(selected, color, pos, bz+0.1f);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
119
source/gui/CDropDown.h
Normal file
119
source/gui/CDropDown.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
GUI Object - Drop Down (list)
|
||||
by Gustav Larsson
|
||||
gee@pyro.nu
|
||||
|
||||
--Overview--
|
||||
|
||||
Works just like a list-box, but it hides
|
||||
all the elements that aren't selected. They
|
||||
can be brought up by pressing the control.
|
||||
|
||||
--More info--
|
||||
|
||||
Check GUI.h
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CDropDown_H
|
||||
#define CDropDown_H
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Includes / Compiler directives
|
||||
//--------------------------------------------------------
|
||||
#include "GUI.h"
|
||||
#include "CList.h"
|
||||
//class CList;
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Macros
|
||||
//--------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Types
|
||||
//--------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Declarations
|
||||
//--------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @author Gustav Larsson
|
||||
*
|
||||
* Drop Down
|
||||
*
|
||||
* The control can be pressed, but we will not inherent
|
||||
* this behavior from IGUIButtonBehavior, because when
|
||||
* you press this control, the list with elements will
|
||||
* immediately appear, and not first after release
|
||||
* (which is the whole gist of the IGUIButtonBehavior).
|
||||
*/
|
||||
class CDropDown : public CList
|
||||
{
|
||||
GUI_OBJECT(CDropDown)
|
||||
|
||||
public:
|
||||
CDropDown();
|
||||
virtual ~CDropDown();
|
||||
|
||||
// virtual void ResetStates() { IGUIButtonBehavior::ResetStates(); }
|
||||
|
||||
/**
|
||||
* Handle Messages
|
||||
*
|
||||
* @param Message GUI Message
|
||||
*/
|
||||
virtual void HandleMessage(const SGUIMessage &Message);
|
||||
|
||||
/**
|
||||
* Handle events manually to catch keyboard inputting.
|
||||
*/
|
||||
virtual int ManuallyHandleEvent(const SDL_Event* ev);
|
||||
|
||||
/**
|
||||
* Draws the Button
|
||||
*/
|
||||
virtual void Draw();
|
||||
|
||||
// This is one of the few classes we actually need to redefine this function
|
||||
// this is because the size of the control changes whether it is open
|
||||
// or closed.
|
||||
virtual bool MouseOver();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Sets up text, should be called every time changes has been
|
||||
* made that can change the visual.
|
||||
*/
|
||||
void SetupText();
|
||||
|
||||
// Sets up the cached GetListRect. Decided whether it should
|
||||
// have a scrollbar, and so on.
|
||||
virtual void SetupListRect();
|
||||
|
||||
// Specify a new List rectangle.
|
||||
virtual CRect GetListRect() const;
|
||||
|
||||
/**
|
||||
* Placement of text.
|
||||
*/
|
||||
CPos m_TextPos;
|
||||
|
||||
// Is the dropdown opened?
|
||||
bool m_Open;
|
||||
|
||||
// I didn't cache this at first, but it's just as easy as caching
|
||||
// m_CachedActualSize, so I thought, what the heck it's used a lot.
|
||||
CRect m_CachedListRect;
|
||||
|
||||
// Hide scrollbar when it's not needed
|
||||
bool m_HideScrollBar;
|
||||
|
||||
// Not necessarily the element that is selected, this is just
|
||||
// which element should be highlighted. When opening the dropdown
|
||||
// it is set to "selected", but then when moving the mouse it will
|
||||
// change.
|
||||
int m_ElementHighlight;
|
||||
};
|
||||
|
||||
#endif
|
6
source/gui/CGUIList.cpp
Normal file
6
source/gui/CGUIList.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "CGUIList.h"
|
||||
|
||||
|
17
source/gui/CGUIList.h
Normal file
17
source/gui/CGUIList.h
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
#ifndef CGUIList_H
|
||||
#define CGUIList_H
|
||||
|
||||
class CGUIList
|
||||
{
|
||||
public: // struct:ish (but for consistency I call it _C_GUIList, and
|
||||
// for the same reason it is a class, so that confusion doesn't
|
||||
// appear when forward declaring.
|
||||
/**
|
||||
* List of items (as text), the post-processed result is stored in
|
||||
* the IGUITextOwner structure of this class.
|
||||
*/
|
||||
std::vector<CGUIString> m_Items;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user