Here's how it looks at close tonight, I've swapped in IGUIStaticPanel (IGUIStaticText) instead of IGUIItem (IGUIButton) to show a working example.
Code: Select all
// Copyright (C) 2006-2012 Michael Zeilfelder
// This file uses the licence of the Irrlicht Engine.
#include "CGUIButtonList.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include "CGUIEditBox.h"
#include "CGUIButton.h"
#include "IGUIEnvironment.h"
#include "IEventReceiver.h"
#include "fast_atof.h"
#include <wchar.h>
namespace irr
{
namespace gui
{
//! constructor
CGUIButtonList::CGUIButtonList(const wchar_t* text, bool border,IGUIEnvironment* environment,
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle)
: IGUIButtonList(environment, parent, id, rectangle),
e_root(0),e_wrap(0),e_scroll_top(0),e_scroll_bottom(0),
attr_styles(0)
{
#ifdef _DEBUG
setDebugName("CGUIButtonList");
#endif
// INITS
last_event = -1;
dragging = 0;
dragging_pos = 0;
scroll_pos = 0;
i_scrollspeed = 5;
/*
// GEN INITIAL FAKE DATA
irr::io::IFileSystem *fs = Environment->getFileSystem();
io::IAttributes *attr; // = fs->createEmptyAttributes(NULL); // driver); // disallows internal loading of textures
attr = fs->createEmptyAttributes(NULL);
attr->addString("label", "Hello");
//attr->addString("src", ""); // change to texture...
items.push_back(attr);
attr = fs->createEmptyAttributes(NULL);
attr->addString("label", "Goodbye");
//attr->addString("src", ""); // change to texture...
items.push_back(attr);
*/
// CREATE ELEMENTS
refresh();
}
//! Refresh
void CGUIButtonList::refresh()
{
// DELETE OLD ROOT PANEL
//IGUIStaticPanel *e_root;
if(e_root)
{
e_root->drop();
e_root = NULL;
}
// DELETE OLD BUTTONS
for(u32 i = 0; i < buttons.size(); i++)
{
//std::cout << "" << points[i].c_str() << std::endl;
//delete items[i];
//items[i] = NULL;
buttons[i]->setVisible(false);
buttons[i]->drop();
}
buttons.clear();
if(e_scroll_top)
{
e_scroll_top->drop();
e_scroll_top = NULL;
}
if(e_scroll_bottom)
{
e_scroll_bottom->drop();
e_scroll_bottom = NULL;
}
if(e_wrap)
{
e_wrap->drop();
e_wrap = NULL;
}
// DEFAULTS
bool show_buttons = false; //false;
s32 btn_h = 20;
s32 btn_scroll = 0;
s32 btn_scroll_h = 0;
// PARSE CORE STYLES
if(attr_styles)
{
s32 id = attr_styles->findAttribute("h");
if(id >= 0){ btn_h = attr_styles->getAttributeAsInt(id); }
id = attr_styles->findAttribute("show_buttons");
if(id >= 0){ show_buttons = attr_styles->getAttributeAsBool(id); }
id = attr_styles->findAttribute("button_h");
if(id >= 0){ btn_scroll_h = attr_styles->getAttributeAsInt(id); }
}
//s32 btn_scroll = 0;
if(show_buttons)
{
btn_scroll = btn_h;
if(btn_scroll_h > 0)
{
btn_scroll = btn_scroll_h; // USE OVERRIDE
}
//e_scroll_top = Environment->addButton(core::rect<s32>(0, btn_h*i, AbsoluteRect.getWidth(), btn_h*(i+1)), e_root);
e_scroll_top = Environment->addItem(core::rect<s32>(0, 0, AbsoluteRect.getWidth(), btn_scroll), this);
e_scroll_top->grab();
e_scroll_top->setSubElement(true);
e_scroll_top->setTabStop(false);
//e_scroll_top->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_CENTER);
//e_scroll_top->setText(items[i]->getAttributeAsStringW("label").c_str());
//e_scroll_bottom = Environment->addButton(core::rect<s32>(0, btn_h*i, AbsoluteRect.getWidth(), btn_h*(i+1)), e_root);
e_scroll_bottom = Environment->addItem(core::rect<s32>(0, AbsoluteRect.getHeight()-btn_scroll, AbsoluteRect.getWidth(), AbsoluteRect.getHeight()), this);
e_scroll_bottom->grab();
e_scroll_bottom->setSubElement(true);
e_scroll_bottom->setTabStop(false);
//e_scroll_bottom->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_CENTER);
//e_scroll_bottom->setText(items[i]->getAttributeAsStringW("label").c_str());
}
// ADD WRAP PANEL
e_wrap = Environment->addStaticPanel(L"", core::rect<s32>(0,btn_scroll,AbsoluteRect.getWidth(),AbsoluteRect.getHeight()-btn_scroll), false, false, this, -1, true);
e_wrap->grab();
e_wrap->setSubElement(true);
//e_wrap->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); // left, right, top, bottom
e_wrap->setBackgroundColor(video::SColor(255,255,255,0));
e_wrap->setDrawBackground(true);
// ADD ROOT PANEL
e_root = Environment->addStaticPanel(L"", core::rect<s32>(0,0,e_wrap->getRelativePosition().getWidth(),e_wrap->getRelativePosition().getHeight()), false, false, e_wrap, -1, true);
e_root->grab();
e_root->setSubElement(true);
//e_root->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); // left, right, top, bottom
e_root->setBackgroundColor(video::SColor(255,255,0,255));
e_root->setDrawBackground(true);
s32 tot_h = 0;
// ADD BUTTONS
//IGUIButton *btn;
//IGUIItem *btn;
IGUIStaticPanel *btn;
for(u32 i = 0; i < items.size(); i++)
{
//btn = Environment->addButton(core::rect<s32>(0, btn_h*i, AbsoluteRect.getWidth(), btn_h*(i+1)), e_root);
//btn = Environment->addItem(core::rect<s32>(0, btn_h*i, e_wrap->getRelativePosition().getWidth(), btn_h*(i+1)), e_root);
btn = Environment->addStaticPanel(items[i]->getAttributeAsStringW("label").c_str(), core::rect<s32>(0, btn_h*i, e_wrap->getRelativePosition().getWidth(), btn_h*(i+1)), false, false, e_root, true);
btn->grab();
btn->setSubElement(true);
btn->setTabStop(false);
//btn->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_CENTER);
//btn->setText(items[i]->getAttributeAsStringW("label").c_str());
buttons.push_back(btn);
tot_h += btn_h;
}
// RESIZE ROOT PANEL
if(tot_h > e_wrap->getRelativePosition().getHeight())
{
//this->setRelativePosition(core::rect<s32>(0,0,AbsoluteRect.getWidth(),tot_h));
e_root->setRelativePosition(core::rect<s32>(0,0,e_wrap->getRelativePosition().getWidth(),tot_h));
//void setRelativePosition (const core::rect< s32 > &r)
//void setRelativePosition (const core::position2di &position);
}
// RESET GLOBALS
scroll_pos = 0;
dragging_pos = 0;
}
void CGUIButtonList::handle_scroll(s32 n)
{
s32 h = e_root->getRelativePosition().getHeight();
s32 eh = e_wrap->getRelativePosition().getHeight();
//if(h > AbsoluteRect.getHeight())
if(h > eh)
{
// SCROLLABLE
scroll_pos += (n*i_scrollspeed);
if(scroll_pos > 0)
{
scroll_pos = 0;
}
else
if(scroll_pos < -(h-eh))
{
scroll_pos = -(h-eh);
}
e_root->setRelativePosition(core::position2di(0, scroll_pos));
}
else
{
// IGNORE
}
}
//! destructor
CGUIButtonList::~CGUIButtonList()
{
for(u32 i = 0; i < items.size(); i++)
{
items[i]->drop();
items[i] = NULL;
}
items.clear();
for(u32 i = 0; i < buttons.size(); i++)
{
buttons[i]->drop();
buttons[i] = NULL;
}
buttons.clear();
if(e_scroll_top)
{
e_scroll_top->drop();
e_scroll_top = NULL;
}
if(e_scroll_bottom)
{
e_scroll_bottom->drop();
e_scroll_bottom = NULL;
}
if(e_root)
{
e_root->drop();
e_root = NULL;
}
if(e_wrap)
{
e_wrap->drop();
e_wrap = NULL;
}
}
bool CGUIButtonList::OnEvent(const SEvent& event)
{
if (IsEnabled)
{
switch(event.EventType)
{
case EET_MOUSE_INPUT_EVENT:
switch(event.MouseInput.Event)
{
case EMIE_MOUSE_WHEEL:
{
handle_scroll((event.MouseInput.Wheel < 0 ? -1.f : 1.f));
}
break;
case EMIE_LMOUSE_PRESSED_DOWN:
{
if(e_wrap->isPointInside(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
{
printf("MOUSE DOWN: INSIDE\n");
dragging = 1;
dragging_pos = event.MouseInput.Y; // STORE
}
}
break;
case EMIE_MOUSE_MOVED:
{
core::position2di mpos = core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y);
if(dragging >= 1) // && e_wrap->isPointInside(mpos))
{
dragging = 2;
s32 diff = dragging_pos - mpos.Y;
scroll_pos -= diff; // UPDATE HERE
handle_scroll(0); // PASS ZERO!!
dragging_pos = mpos.Y; // STORE
}
}
break;
case EMIE_LMOUSE_LEFT_UP:
{
if(dragging == 1) // NO DRAG
{
if(e_wrap->isPointInside(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
{
IGUIElement *e = Environment->getRootGUIElement()->getElementFromPoint(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
if(e && e != Environment->getRootGUIElement())
{
for(u32 i = 0; i < buttons.size(); i++)
{
if(buttons[i] == e)
{
printf("Found our button....! %d \n", i);
// STORE
last_event = i;
// SEND EVENT
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_BUTTONLIST_CLICKED;
if ( Parent )
Parent->OnEvent(e);
// CLEAR
dragging = 0;
dragging_pos = 0;
// CLAIM THIS EVENT
return true;
//break;
}
}
}
}
}
else
if(dragging == 2) // DRAG HAPPENED
{
//printf("Dragging happened!\n");
}
// CLEAR
dragging = 0;
dragging_pos = 0;
}
break;
default:
break;
}
break;
case EET_GUI_EVENT:
if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
{
/*
for(u32 i = 0; i < buttons.size(); i++)
{
if(event.GUIEvent.Caller == buttons[i])
{
printf("Found\n");
//virtual io::IAttributes *get_last_event();
last_event = i;
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_BUTTONLIST_CLICKED;
if ( Parent )
Parent->OnEvent(e);
return true;
}
}
*/
// SCROLL BUTTON TESTING
if(e_scroll_top && event.GUIEvent.Caller == e_scroll_top)
{
handle_scroll(1);
return true;
}
else
if(e_scroll_bottom && event.GUIEvent.Caller == e_scroll_bottom)
{
handle_scroll(-1);
return true;
}
}
break;
default:
break;
}
}
return IGUIElement::OnEvent(event);
}
void CGUIButtonList::draw()
{
if ( !isVisible() )
return;
IGUIButtonList::draw();
}
//! Writes attributes of the element.
void CGUIButtonList::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
IGUIElement::serializeAttributes(out, options);
/*
out->addFloat("Min", getMin());
out->addFloat("Max", getMax());
out->addFloat("Step", getStepSize());
out->addInt("DecimalPlaces", DecimalPlaces);
*/
}
//! Reads attributes of the element
void CGUIButtonList::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
IGUIElement::deserializeAttributes(in, options);
/*
setRange(in->getAttributeAsFloat("Min"), in->getAttributeAsFloat("Max"));
setStepSize(in->getAttributeAsFloat("Step"));
setDecimalPlaces(in->getAttributeAsInt("DecimalPlaces"));
*/
}
void CGUIButtonList::set_styles(io::IAttributes *attr, bool do_refresh)
{
attr_styles = attr;
if(attr_styles)
{
s32 id = attr_styles->findAttribute("scrollspeed");
if(id >= 0){ i_scrollspeed = attr_styles->getAttributeAsInt(id); }
}
if(do_refresh)
{
// REFRESH
refresh();
}
}
void CGUIButtonList::set_style(core::stringc key, core::stringc value, bool do_refresh)
{
//attr_styles
}
core::stringc CGUIButtonList::get_style(core::stringc key) const
{
return "";
}
void CGUIButtonList::clear_items(bool do_refresh)
{
// DELETE
for(u32 i = 0; i < items.size(); i++)
{
items[i]->drop();
items[i] = NULL;
}
items.clear();
last_event = -1;
if(do_refresh)
{
// REFRESH
refresh();
}
}
void CGUIButtonList::set_items(core::array<io::IAttributes*> new_items)
{
// DELETE OLD
clear_items(false);
// SET ITEM
items = new_items;
// REFRESH
refresh();
}
void CGUIButtonList::add_item(io::IAttributes *item, bool do_refresh)
{
if(item)
{
// ADD
items.push_back(item);
if(do_refresh)
{
// REFRESH
refresh();
}
}
}
//! Returns the item and not the button
io::IAttributes *CGUIButtonList::get_last_event()
{
if(last_event >= 0 && last_event < items.size())
{
return items[last_event];
}
return NULL;
}
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_