fixed bugs with listbox automatic visibility of scrollbars, and clicking on listbox scrollbars when in a combo box.

items in a listbox are now selected as you type their text.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@799 dfc29bdd-3216-0410-991c-e03cc46cb475
master
bitplane 2007-07-18 22:47:05 +00:00
parent 3f4fb37f5e
commit 1d6a992ee0
4 changed files with 124 additions and 31 deletions

View File

@ -124,9 +124,11 @@ GUI:
- IGUIStaticText new methods setDrawBorder and setTextAlignment. - IGUIStaticText new methods setDrawBorder and setTextAlignment.
- Added IGUIListBox::setAutoScrollEnabled and isAutoScrollEnabled, for automatic - IGUIListBox changes:
scrolling when selecting or adding an item. Scrollbars are now only visible Added setAutoScrollEnabled and isAutoScrollEnabled, for automatic scrolling
when the list doesn't fit in the visible area. when selecting or adding an item.
Scrollbars are now only visible when the list doesn't fit in the visible area.
You can now type an item's text to select it.
Changes in version 1.3.1 (20 Jun 2007) Changes in version 1.3.1 (20 Jun 2007)

View File

@ -199,7 +199,7 @@ bool CGUIComboBox::OnEvent(SEvent event)
if (Selected <0) if (Selected <0)
Selected = 0; Selected = 0;
else
if (Selected >= (s32)Items.size()) if (Selected >= (s32)Items.size())
Selected = (s32)Items.size() -1; Selected = (s32)Items.size() -1;
@ -216,9 +216,12 @@ bool CGUIComboBox::OnEvent(SEvent event)
switch(event.GUIEvent.EventType) switch(event.GUIEvent.EventType)
{ {
case EGET_ELEMENT_FOCUS_LOST: case EGET_ELEMENT_FOCUS_LOST:
if (Environment->hasFocus(ListBox) && if (ListBox &&
(Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) &&
event.GUIEvent.Element != this && event.GUIEvent.Element != this &&
event.GUIEvent.Element != ListButton) event.GUIEvent.Element != ListButton &&
event.GUIEvent.Element != ListBox &&
!ListBox->isMyChild(event.GUIEvent.Element))
{ {
openCloseMenu(); openCloseMenu();
} }
@ -279,6 +282,20 @@ bool CGUIComboBox::OnEvent(SEvent event)
} }
} }
break; break;
case EMIE_MOUSE_WHEEL:
{
s32 oldSelected = Selected;
Selected += (event.MouseInput.Wheel < 0) ? 1 : -1;
if (Selected <0)
Selected = 0;
if (Selected >= (s32)Items.size())
Selected = (s32)Items.size() -1;
if (Selected != oldSelected)
sendSelectionChangedEvent();
}
} }
break; break;
} }

View File

@ -23,7 +23,8 @@ CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent,
: IGUIListBox(environment, parent, id, rectangle), Selected(-1), ItemHeight(0), : IGUIListBox(environment, parent, id, rectangle), Selected(-1), ItemHeight(0),
TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0), TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0),
ScrollBar(0), Selecting(false), DrawBack(drawBack), ScrollBar(0), Selecting(false), DrawBack(drawBack),
MoveOverSelect(moveOverSelect), selectTime(0), AutoScroll(true) MoveOverSelect(moveOverSelect), selectTime(0), AutoScroll(true),
KeyBuffer(), LastKeyTime(0), HighlightWhenNotFocused(true)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CGUIListBox"); setDebugName("CGUIListBox");
@ -170,7 +171,7 @@ void CGUIListBox::recalculateItemHeight()
TotalItemHeight = ItemHeight * Items.size(); TotalItemHeight = ItemHeight * Items.size();
ScrollBar->setMax(TotalItemHeight - AbsoluteRect.getHeight()); ScrollBar->setMax(TotalItemHeight - AbsoluteRect.getHeight());
if( TotalItemHeight < AbsoluteRect.getHeight() ) if( TotalItemHeight <= AbsoluteRect.getHeight() )
ScrollBar->setVisible(false); ScrollBar->setVisible(false);
else else
ScrollBar->setVisible(true); ScrollBar->setVisible(true);
@ -276,6 +277,85 @@ bool CGUIListBox::OnEvent(SEvent event)
} }
return true; return true;
} }
else if (event.KeyInput.PressedDown && event.KeyInput.Char)
{
// change selection based on text as it is typed.
u32 now = os::Timer::getTime();
if (now - LastKeyTime < 500)
{
// add to key buffer if it isn't a key repeat
if (!(KeyBuffer.size() == 1 && KeyBuffer[0] == event.KeyInput.Char))
{
KeyBuffer += L" ";
KeyBuffer[KeyBuffer.size()-1] = event.KeyInput.Char;
}
}
else
{
KeyBuffer = L" ";
KeyBuffer[0] = event.KeyInput.Char;
}
LastKeyTime = now;
// find the selected item, starting at the current selection
s32 start = Selected;
s32 current = start+1;
// dont change selection if the key buffer matches the current item
if (Selected > -1 && KeyBuffer.size() > 1)
{
if (Items[Selected].text.size() >= KeyBuffer.size() &&
KeyBuffer.equals_ignore_case(Items[Selected].text.subString(0,KeyBuffer.size())))
return true;
}
while (current < (s32)Items.size())
{
if (Items[current].text.size() >= KeyBuffer.size())
{
if (KeyBuffer.equals_ignore_case(Items[current].text.subString(0,KeyBuffer.size())))
{
if (Parent && Selected != current && !Selecting && !MoveOverSelect)
{
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;
Parent->OnEvent(e);
}
setSelected(current);
return true;
}
}
current++;
}
current = 0;
while (current <= start)
{
if (Items[current].text.size() >= KeyBuffer.size())
{
if (KeyBuffer.equals_ignore_case(Items[current].text.subString(0,KeyBuffer.size())))
{
if (Parent && Selected != current && !Selecting && !MoveOverSelect)
{
Selected = current;
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;
Parent->OnEvent(e);
}
setSelected(current);
return true;
}
}
current++;
}
return true;
}
break; break;
case EET_GUI_EVENT: case EET_GUI_EVENT:
@ -306,26 +386,11 @@ bool CGUIListBox::OnEvent(SEvent event)
case EMIE_LMOUSE_PRESSED_DOWN: case EMIE_LMOUSE_PRESSED_DOWN:
{ {
IGUIElement *el = Environment->getRootGUIElement()->getElementFromPoint(
core::position2di(event.MouseInput.X, event.MouseInput.Y));
if (Environment->hasFocus(this) &&
ScrollBar == el &&
ScrollBar->OnEvent(event))
{
return true;
}
Selecting = true; Selecting = true;
Environment->setFocus(this);
return true; return true;
} }
case EMIE_LMOUSE_LEFT_UP: case EMIE_LMOUSE_LEFT_UP:
if (Environment->hasFocus(this) &&
ScrollBar->isPointInside(p) &&
ScrollBar->OnEvent(event))
return true;
if (!isPointInside(p)) if (!isPointInside(p))
{ {
@ -372,8 +437,9 @@ void CGUIListBox::selectNew(s32 ypos, bool onlyHover)
if (Selected<0) if (Selected<0)
Selected = 0; Selected = 0;
// post the news recalculateScrollPos();
// post the news
if (Parent && !onlyHover) if (Parent && !onlyHover)
{ {
SEvent event; SEvent event;
@ -413,6 +479,7 @@ void CGUIListBox::draw()
core::rect<s32> clientClip(AbsoluteRect); core::rect<s32> clientClip(AbsoluteRect);
clientClip.UpperLeftCorner.Y += 1; clientClip.UpperLeftCorner.Y += 1;
clientClip.UpperLeftCorner.X += 1; clientClip.UpperLeftCorner.X += 1;
if (ScrollBar->isVisible())
clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE); clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE);
clientClip.LowerRightCorner.Y -= 1; clientClip.LowerRightCorner.Y -= 1;
clientClip.clipAgainst(AbsoluteClippingRect); clientClip.clipAgainst(AbsoluteClippingRect);
@ -425,18 +492,22 @@ void CGUIListBox::draw()
frameRect = AbsoluteRect; frameRect = AbsoluteRect;
frameRect.UpperLeftCorner.X += 1; frameRect.UpperLeftCorner.X += 1;
if (ScrollBar->isVisible())
frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE); frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE);
frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight; frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight;
frameRect.UpperLeftCorner.Y -= ScrollBar->getPos(); frameRect.UpperLeftCorner.Y -= ScrollBar->getPos();
frameRect.LowerRightCorner.Y -= ScrollBar->getPos(); frameRect.LowerRightCorner.Y -= ScrollBar->getPos();
bool hl = (HighlightWhenNotFocused || Environment->hasFocus(this) || Environment->hasFocus(ScrollBar));
for (s32 i=0; i<(s32)Items.size(); ++i) for (s32 i=0; i<(s32)Items.size(); ++i)
{ {
if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y && if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y &&
frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y) frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y)
{ {
if (i == Selected) if (i == Selected && hl)
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip); skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip);
core::rect<s32> textRect = frameRect; core::rect<s32> textRect = frameRect;
@ -450,13 +521,13 @@ void CGUIListBox::draw()
iconPos.Y += textRect.getHeight() / 2; iconPos.Y += textRect.getHeight() / 2;
iconPos.X += ItemsIconWidth/2; iconPos.X += ItemsIconWidth/2;
IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip, IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip,
skin->getColor((i==Selected) ? EGDC_ICON_HIGH_LIGHT : EGDC_ICON), skin->getColor((i==Selected && hl) ? EGDC_ICON_HIGH_LIGHT : EGDC_ICON),
(i==Selected) ? selectTime : 0 , (i==Selected) ? os::Timer::getTime() : 0, false, true); (i==Selected && hl) ? selectTime : 0 , (i==Selected) ? os::Timer::getTime() : 0, false, true);
} }
textRect.UpperLeftCorner.X += ItemsIconWidth+3; textRect.UpperLeftCorner.X += ItemsIconWidth+3;
Font->draw(Items[i].text.c_str(), textRect, skin->getColor((i==Selected) ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT), false, true, &clientClip); Font->draw(Items[i].text.c_str(), textRect, skin->getColor((i==Selected && hl) ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT), false, true, &clientClip);
textRect.UpperLeftCorner.X -= ItemsIconWidth+3; textRect.UpperLeftCorner.X -= ItemsIconWidth+3;
} }

View File

@ -113,6 +113,9 @@ namespace gui
bool MoveOverSelect; bool MoveOverSelect;
u32 selectTime; u32 selectTime;
bool AutoScroll; bool AutoScroll;
core::stringw KeyBuffer;
u32 LastKeyTime;
bool HighlightWhenNotFocused;
}; };