Retour
Version Originale

./aip/1.8aipmod/source/Irrlicht/CGUIComboBox.cpp :


// Copyright (C) 2002-2011 Nikolaus Gebhardt

// This file is part of the "Irrlicht Engine".

// For conditions of distribution and use, see copyright notice in irrlicht.h


#include "CGUIComboBox.h"
#ifdef _IRR_COMPILE_WITH_GUI_

#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IGUIFont.h"
#include "IGUIButton.h"
#include "CGUIListBox.h"
#include "os.h"

namespace irr
{
namespace gui
{

//! constructor

CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
	s32 id, core::rect<s32> rectangle)
	: IGUIComboBox(environment, parent, id, rectangle),
	ListButton(0), SelectedText(0), ListBox(0), LastFocus(0),
	Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), HasFocus(false)
{
	#ifdef _DEBUG
	setDebugName("CGUIComboBox");
	#endif

	IGUISkin* skin = Environment->getSkin();

	s32 width = 15;
	if (skin)
		width = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);

	core::rect<s32> r;
	r.UpperLeftCorner.X = rectangle.getWidth() - width - 2;
	r.LowerRightCorner.X = rectangle.getWidth() - 2;

	r.UpperLeftCorner.Y = 2;
	r.LowerRightCorner.Y = rectangle.getHeight() - 2;

	ListButton = Environment->addButton(r, this, -1, L"");
	if (skin && skin->getSpriteBank())
	{
		ListButton->setSpriteBank(skin->getSpriteBank());
		ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
		ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
	}
	ListButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
	ListButton->setSubElement(true);
	ListButton->setTabStop(false);

	r.UpperLeftCorner.X = 2;
	r.UpperLeftCorner.Y = 2;
	r.LowerRightCorner.X = RelativeRect.getWidth() - (ListButton->getAbsolutePosition().getWidth() + 2);
	r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;

	SelectedText = Environment->addStaticText(L"", r, false, false, this, -1, false);
	SelectedText->setSubElement(true);
	SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
	SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER);
	if (skin)
		SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT));
	SelectedText->enableOverrideColor(true);

	// this element can be tabbed to

	setTabStop(true);
	setTabOrder(-1);
}


void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
{
	HAlign = horizontal;
	VAlign = vertical;
	SelectedText->setTextAlignment(horizontal, vertical);
}


//! Returns amount of items in box

u32 CGUIComboBox::getItemCount() const
{
	return Items.size();
}


//! returns string of an item. the idx may be a value from 0 to itemCount-1

const wchar_t* CGUIComboBox::getItem(u32 idx) const
{
	if (idx >= Items.size())
		return 0;

	return Items[idx].Name.c_str();
}

//! returns string of an item. the idx may be a value from 0 to itemCount-1

u32 CGUIComboBox::getItemData(u32 idx) const
{
	if (idx >= Items.size())
		return 0;

	return Items[idx].Data;
}

//! Returns index based on item data

s32 CGUIComboBox::getIndexForItemData(u32 data ) const
{
	for ( u32 i = 0; i < Items.size (); ++i )
	{
		if ( Items[i].Data == data )
			return i;
	}
	return -1;
}


//! Removes an item from the combo box.

void CGUIComboBox::removeItem(u32 idx)
{
	if (idx >= Items.size())
		return;

	if (Selected == (s32)idx)
		setSelected(-1);

	Items.erase(idx);
}


//! Returns caption of this element.

const wchar_t* CGUIComboBox::getText() const
{
	return getItem(Selected);
}


//! adds an item and returns the index of it

u32 CGUIComboBox::addItem(const wchar_t* text, u32 data)
{
	Items.push_back( SComboData ( text, data ) );

	if (Selected == -1)
		setSelected(0);

	return Items.size() - 1;
}


//! deletes all items in the combo box

void CGUIComboBox::clear()
{
	Items.clear();
	setSelected(-1);
}


//! returns id of selected item. returns -1 if no item is selected.

s32 CGUIComboBox::getSelected() const
{
	return Selected;
}


//! sets the selected item. Set this to -1 if no item should be selected

void CGUIComboBox::setSelected(s32 idx)
{
	if (idx < -1 || idx >= (s32)Items.size())
		return;

	Selected = idx;
	if (Selected == -1)
		SelectedText->setText(L"");
	else
		SelectedText->setText(Items[Selected].Name.c_str());
}


//! called if an event happened.

bool CGUIComboBox::OnEvent(const SEvent& event)
{
	if (isEnabled())
	{
		switch(event.EventType)
		{

		case EET_KEY_INPUT_EVENT:
			if (ListBox && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
			{
				// hide list box

				openCloseMenu();
				return true;
			}
			else
			if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)
			{
				if (!event.KeyInput.PressedDown)
				{
					openCloseMenu();
				}

				ListButton->setPressed(ListBox == 0);

				return true;
			}
			else
			if (event.KeyInput.PressedDown)
			{
				s32 oldSelected = Selected;
				bool absorb = true;
				switch (event.KeyInput.Key)
				{
					case KEY_DOWN:
						setSelected(Selected+1);
						break;
					case KEY_UP:
						setSelected(Selected-1);
						break;
					case KEY_HOME:
					case KEY_PRIOR:
						setSelected(0);
						break;
					case KEY_END:
					case KEY_NEXT:
						setSelected((s32)Items.size()-1);
						break;
					default:
						absorb = false;
				}

				if (Selected <0)
					setSelected(0);

				if (Selected >= (s32)Items.size())
					setSelected((s32)Items.size() -1);

				if (Selected != oldSelected)
					sendSelectionChangedEvent();

				if (absorb)
					return true;
			}
			break;

		case EET_GUI_EVENT:

			switch(event.GUIEvent.EventType)
			{
			case EGET_ELEMENT_FOCUS_LOST:
				if (ListBox &&
					(Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) &&
					event.GUIEvent.Element != this &&
					!isMyChild(event.GUIEvent.Element) &&
					!ListBox->isMyChild(event.GUIEvent.Element))
				{
					openCloseMenu();
				}
				break;
			case EGET_BUTTON_CLICKED:
				if (event.GUIEvent.Caller == ListButton)
				{
					openCloseMenu();
					return true;
				}
				break;
			case EGET_LISTBOX_SELECTED_AGAIN:
			case EGET_LISTBOX_CHANGED:
				if (event.GUIEvent.Caller == ListBox)
				{
					setSelected(ListBox->getSelected());
					if (Selected <0 || Selected >= (s32)Items.size())
						setSelected(-1);
					openCloseMenu();

					sendSelectionChangedEvent();
				}
				return true;
			default:
				break;
			}
			break;
		case EET_MOUSE_INPUT_EVENT:

			switch(event.MouseInput.Event)
			{
			case EMIE_LMOUSE_PRESSED_DOWN:
				{
					core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);

					// send to list box

					if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event))
						return true;

					return true;
				}
			case EMIE_LMOUSE_LEFT_UP:
				{
					core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);

					// send to list box

					if (!(ListBox &&
							ListBox->getAbsolutePosition().isPointInside(p) &&
							ListBox->OnEvent(event)))
					{
						openCloseMenu();
					}
					return true;
				}
			case EMIE_MOUSE_WHEEL:
				{
					s32 oldSelected = Selected;
					setSelected( Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1));

					if (Selected <0)
						setSelected(0);

					if (Selected >= (s32)Items.size())
						setSelected((s32)Items.size() -1);

					if (Selected != oldSelected)
						sendSelectionChangedEvent();
				}
			default:
				break;
			}
			break;
		default:
			break;
		}
	}

	return IGUIElement::OnEvent(event);
}


void CGUIComboBox::sendSelectionChangedEvent()
{
	if (Parent)
	{
		SEvent event;

		event.EventType = EET_GUI_EVENT;
		event.GUIEvent.Caller = this;
		event.GUIEvent.Element = 0;
		event.GUIEvent.EventType = EGET_COMBO_BOX_CHANGED;
		Parent->OnEvent(event);
	}
}


//! draws the element and its children

void CGUIComboBox::draw()
{
	if (!IsVisible)
		return;

	IGUISkin* skin = Environment->getSkin();
	IGUIElement *currentFocus = Environment->getFocus();
	if (currentFocus != LastFocus)
	{
		HasFocus = currentFocus == this || isMyChild(currentFocus);
		LastFocus = currentFocus;
	}

	// set colors each time as skin-colors can be changed

	SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT));
	if(isEnabled())
	{
		SelectedText->setDrawBackground(HasFocus);
		SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT));
	}
	else
	{
		SelectedText->setDrawBackground(false);
		SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT));
	}
	ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
	ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));


	core::rect<s32> frameRect(AbsoluteRect);

	// draw the border


	skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT),
		true, true, frameRect, &AbsoluteClippingRect);

	// draw children

	IGUIElement::draw();
}


void CGUIComboBox::openCloseMenu()
{
	if (ListBox)
	{
		// close list box

		Environment->setFocus(this);
		ListBox->remove();
		ListBox = 0;
	}
	else
	{
		if (Parent)
			Parent->bringToFront(this);

		IGUISkin* skin = Environment->getSkin();
		s32 h = Items.size();

		if (h > 5)
			h = 5;
		if (h == 0)
			h = 1;

		IGUIFont* font = skin->getFont();
		if (font)
			h *= (font->getDimension(L"A").Height + 4);

		// open list box

		core::rect<s32> r(0, AbsoluteRect.getHeight(),
			AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h);

		ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true);
		ListBox->setSubElement(true);
		ListBox->setNotClipped(true);
		ListBox->drop();

		// ensure that list box is always completely visible

		if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight())
			ListBox->setRelativePosition( core::rect<s32>(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0) );

		for (s32 i=0; i<(s32)Items.size(); ++i)
			ListBox->addItem(Items[i].Name.c_str());

		ListBox->setSelected(Selected);

		// set focus

		Environment->setFocus(ListBox);
	}
}


//! Writes attributes of the element.

void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
{
	IGUIComboBox::serializeAttributes(out,options);

	out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
	out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);

	out->addInt	("Selected",	Selected );
	out->addInt	("ItemCount",	Items.size());
	for (u32 i=0; i < Items.size(); ++i)
	{
		core::stringc s = "Item";
		s += i;
		s += "Text";
		out->addString(s.c_str(), Items[i].Name.c_str());
	}
}


//! Reads attributes of the element

void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
{
	IGUIComboBox::deserializeAttributes(in,options);

	setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
                      (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));

	// clear the list

	clear();
	// get item count

	u32 c = in->getAttributeAsInt("ItemCount");
	// add items

	for (u32 i=0; i < c; ++i)
	{
		core::stringc s = "Item";
		s += i;
		s += "Text";
		addItem(in->getAttributeAsStringW(s.c_str()).c_str(), 0);
	}

	setSelected(in->getAttributeAsInt("Selected"));
}

} // end namespace gui

} // end namespace irr



#endif // _IRR_COMPILE_WITH_GUI_


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
881 membres
1426 sujets
11116 messages
Dernier membre inscrit: Bidule
14 invités en ligne
Aucun membre connecté
RSS Feed