irrlicht/source/Irrlicht/CGUIColorSelectDialog.cpp
bitplane e0a66f229b Added navigation through the GUI using tab and the shift and control keys. Added keyboard navigation for most elements. Fixed that annoying bug where you had to click twice to change focus.
Added IGUIElement::isMyChild, isPointInside,  SEvent.GUIEvent.Element. 
Changed setFocus and removeFocus to return bools.
changed quaternion::toAngleAxis to use iszero. 

git-svn-id: http://svn.code.sf.net/p/irrlicht/code/trunk@763 dfc29bdd-3216-0410-991c-e03cc46cb475
2007-07-07 07:03:54 +00:00

485 lines
12 KiB
C++

// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CGUIColorSelectDialog.h"
#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "IGUIButton.h"
#include "IGUIStaticText.h"
#include "IGUIFont.h"
#include "IGUISpriteBank.h"
#include "IFileList.h"
#include "os.h"
#include "SoftwareDriver2_helper.h"
#include "CImage.h"
namespace irr
{
namespace gui
{
const s32 CSD_WIDTH = 350;
const s32 CSD_HEIGHT = 300;
struct sTemplate
{
const wchar_t *pre;
const wchar_t *init;
const wchar_t *pos;
int x, y;
int range_down ,range_up;
};
static const sTemplate Template [] =
{
{ L"A:", L"0", 0,20,165, 0, 255 },
{ L"R:", L"0", 0,20,205, 0, 255 },
{ L"G:", L"0", 0,20,230, 0, 255 },
{ L"B:", L"0", 0,20,255, 0, 255 },
{ L"H:", L"0", L"°",180,205, 0, 360 },
{ L"S:", L"0", L"%",180,230, 0, 100 },
{ L"L:", L"0", L"%",180,255, 0, 100 },
};
//! constructor
CGUIColorSelectDialog::CGUIColorSelectDialog( const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id)
: IGUIColorSelectDialog(environment, parent, id,
core::rect<s32>((parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2,
(parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2,
(parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2+CSD_WIDTH,
(parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2+CSD_HEIGHT)),
Dragging(false)
{
#ifdef _DEBUG
IGUIElement::setDebugName("CGUIColorSelectDialog");
#endif
Text = title;
IGUISkin* skin = Environment->getSkin();
core::rect<s32> rec;
s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH);
s32 posx = RelativeRect.getWidth() - buttonw - 4;
CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw),
this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
if (skin && skin->getSpriteBank())
{
CloseButton->setSpriteBank(skin->getSpriteBank());
CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
}
CloseButton->setSubElement(true);
CloseButton->setTabStop(false);
CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
CloseButton->grab();
OKButton = Environment->addButton(
core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
OKButton->setSubElement(true);
OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
OKButton->grab();
CancelButton = Environment->addButton(
core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
CancelButton->setSubElement(true);
CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
CancelButton->grab();
core::rect<s32> r;
video::IVideoDriver* driver = Environment->getVideoDriver();
ColorRing.Texture = driver->getTexture ( "#colorring" );
if ( 0 == ColorRing.Texture )
{
buildColorRing(core::dimension2d<s32>(128, 128), 1,
Environment->getSkin()->getColor(EGDC_3D_SHADOW).color);
}
r.UpperLeftCorner.X = 20;
r.UpperLeftCorner.Y = 20;
ColorRing.Control = Environment->addImage(ColorRing.Texture, r.UpperLeftCorner, true, this);
ColorRing.Control->setSubElement(true);
ColorRing.Control->grab();
for ( u32 i = 0; i != sizeof (Template) / sizeof ( sTemplate ); ++i )
{
if ( Template[i].pre )
{
r.UpperLeftCorner.X = Template[i].x;
r.UpperLeftCorner.Y = Template[i].y;
r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
IGUIElement *t = Environment->addStaticText( Template[i].pre, r, false, false, this);
t->setSubElement(true);
}
if ( Template[i].pos )
{
r.UpperLeftCorner.X = Template[i].x + 52;
r.UpperLeftCorner.Y = Template[i].y;
r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
IGUIElement *t = Environment->addStaticText( Template[i].pos, r, false, false, this);
t->setSubElement(true);
}
SBatteryItem item;
r.UpperLeftCorner.X = Template[i].x + 15;
r.UpperLeftCorner.Y = Template[i].y;
r.LowerRightCorner.X = r.UpperLeftCorner.X + 35;
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
item.Edit = Environment->addEditBox( Template[i].init, r, true, this);
item.Edit->setSubElement(true);
item.Edit->grab();
r.UpperLeftCorner.X = Template[i].x + 70;
r.UpperLeftCorner.Y = Template[i].y + 4;
r.LowerRightCorner.X = r.UpperLeftCorner.X + 60;
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 12;
item.Scrollbar = Environment->addScrollBar(true, r, this);
item.Scrollbar->grab ();
item.Scrollbar->setSubElement(true);
item.Scrollbar->setMax ( Template[i].range_up - Template[i].range_down );
item.Scrollbar->setSmallStep ( 1 );
Battery.push_back ( item );
}
bringToFront(CancelButton);
bringToFront(OKButton);
}
//! destructor
CGUIColorSelectDialog::~CGUIColorSelectDialog()
{
if (CloseButton)
CloseButton->drop();
if (OKButton)
OKButton->drop();
if (CancelButton)
CancelButton->drop();
for ( u32 i = 0; i != Battery.size ();++i )
{
Battery[i].Edit->drop ();
Battery[i].Scrollbar->drop ();
}
if ( ColorRing.Control )
{
ColorRing.Control->drop ();
}
}
//! renders a antialiased, colored ring
void CGUIColorSelectDialog::buildColorRing( const core::dimension2d<s32> & dim, s32 supersample, const u32 borderColor )
{
video::CImage *RawTexture;
core::dimension2d<s32> d;
d.Width = dim.Width * supersample;
d.Height = dim.Height * supersample;
RawTexture = new video::CImage ( irr::video::ECF_A8R8G8B8, d );
RawTexture->fill ( 0x00808080 );
u8 * data= (u8*) RawTexture->lock();
const u32 pitch = RawTexture->getPitch ();
s32 radiusOut = ( d.Width / 2 ) - 4;
const s32 fullR2 = radiusOut * radiusOut;
video::SColorHSL hsl;
video::SColor rgb;
rgb.color = 0xFF000000;
hsl.Luminance = 0.5f;
hsl.Saturation = 1.f;
core::position2d<s32> p;
u32 *dst;
for ( p.Y = -radiusOut; p.Y <= radiusOut; p.Y += 1 )
{
s32 y2 = p.Y * p.Y;
dst = (u32*) ( (u8* ) data + ( ( 4 + p.Y + radiusOut ) * pitch ) + (4 << 2 ) );
for ( p.X = -radiusOut; p.X <= radiusOut; p.X += 1, dst += 1 )
{
s32 r2 = y2 + ( p.X * p.X );
// test point in circle
s32 testa = r2 - fullR2;
if ( testa < 0 )
{
// dotproduct u ( x,y ) * v ( 1, 0 ) = cosinus(a)
f32 r = (f32) sqrt ( (f32) r2 );
// normalize, dotproduct = xnorm
f32 t = (f32) 1.0 / r;
f32 xn = -p.X * t;
hsl.Hue = (f32) acos ( xn );
if ( p.Y > 0 )
hsl.Hue = (2.f * core::PI ) - hsl.Hue;
hsl.Hue -= core::PI / 2.f;
f32 rTest = r / radiusOut;
/*
if ( rTest < 0.25f )
{
hsl.Luminance = rTest / 0.25f;
hsl.Saturation = 0.f;
hsl.settoRGB ( rgb );
*dst = rgb.color;
}
else
if ( rTest < 0.4f )
{
hsl.Saturation = ( rTest - 0.25f ) / 0.15f;
hsl.Luminance = 1.f - ( hsl.Saturation / 2.4f );
hsl.Luminance = 0.5f;
hsl.settoRGB ( rgb );
// *dst = rgb.color;
}
else
if ( rTest < 0.75f )
{
hsl.Luminance = 0.5f;
hsl.Saturation = 1.f;
hsl.settoRGB ( rgb );
*dst = rgb.color;
}
else
if ( rTest < 0.98f )
{
hsl.Luminance = 0.5f - ( ( rTest - 0.75f ) / 0.75f );
hsl.Saturation = 1.f;
hsl.settoRGB ( rgb );
*dst = rgb.color;
}
*/
if ( rTest >= 0.5f )
{
hsl.Luminance = 0.5f;
hsl.Saturation = 1.f;
hsl.settoRGB ( rgb );
*dst = rgb.color;
}
if ( rTest >= 0.5f && rTest <= 0.55f )
{
u32 alpha = (s32) ( (rTest - 0.5f ) * ( 255.f / 0.05f ) );
*dst = *dst & 0x00ffffff | (alpha << 24);
}
if ( rTest >= 0.95f )
{
u32 alpha = (s32) ( (rTest - 0.95f ) * ( 255.f / 0.05f ) );
alpha = 255 - alpha;
*dst = *dst & 0x00ffffff | (alpha << 24);
}
}
}
}
RawTexture->unlock ();
if ( supersample > 1 )
{
video::CImage * filter = new video::CImage(irr::video::ECF_A8R8G8B8, dim );
RawTexture->copyToScalingBoxFilter ( filter, 0 );
RawTexture->drop ();
RawTexture = filter;
}
video::IVideoDriver* driver = Environment->getVideoDriver();
bool generateMipLevels = driver->getTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS );
driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false);
ColorRing.Texture = driver->addTexture ( "#colorring", RawTexture );
RawTexture->drop ();
driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, generateMipLevels);
}
//! called if an event happened.
bool CGUIColorSelectDialog::OnEvent(SEvent event)
{
switch(event.EventType)
{
case EET_GUI_EVENT:
switch(event.GUIEvent.EventType)
{
case EGET_SCROLL_BAR_CHANGED:
{
for ( u32 i = 0; i!= Battery.size (); ++i )
{
if ( event.GUIEvent.Caller == Battery[i].Scrollbar )
{
s32 pos = Battery[i].Scrollbar->getPos ();
s32 value = Template[i].range_down + ( pos );
core::stringw s ( value );
Battery[i].Edit->setText ( s.c_str() );
}
}
return true;
} break;
case EGET_ELEMENT_FOCUS_LOST:
Dragging = false;
break;
case EGET_BUTTON_CLICKED:
if (event.GUIEvent.Caller == CloseButton ||
event.GUIEvent.Caller == CancelButton)
{
sendCancelEvent();
remove();
return true;
}
else
if (event.GUIEvent.Caller == OKButton)
{
sendSelectedEvent();
remove();
return true;
}
break;
case EGET_LISTBOX_CHANGED:
{
}
break;
case EGET_LISTBOX_SELECTED_AGAIN:
{
}
break;
}
break;
case EET_MOUSE_INPUT_EVENT:
switch(event.MouseInput.Event)
{
case EMIE_LMOUSE_PRESSED_DOWN:
DragStart.X = event.MouseInput.X;
DragStart.Y = event.MouseInput.Y;
Dragging = true;
Environment->setFocus(this);
return true;
case EMIE_LMOUSE_LEFT_UP:
Dragging = false;
Environment->removeFocus(this);
return true;
case EMIE_MOUSE_MOVED:
if (Dragging)
{
// gui window should not be dragged outside its parent
if (Parent)
if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)
return true;
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
DragStart.X = event.MouseInput.X;
DragStart.Y = event.MouseInput.Y;
return true;
}
break;
}
}
return Parent ? Parent->OnEvent(event) : false;
}
//! draws the element and its children
void CGUIColorSelectDialog::draw()
{
if (!IsVisible)
return;
IGUISkin* skin = Environment->getSkin();
core::rect<s32> rect = AbsoluteRect;
rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
rect, &AbsoluteClippingRect);
if (Text.size())
{
rect.UpperLeftCorner.X += 2;
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
IGUIFont* font = skin->getFont(EGDF_WINDOW);
if (font)
font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true,
&AbsoluteClippingRect);
}
IGUIElement::draw();
}
//! sends the event that the file has been selected.
void CGUIColorSelectDialog::sendSelectedEvent()
{
SEvent event;
event.EventType = EET_GUI_EVENT;
event.GUIEvent.Caller = this;
event.GUIEvent.Element = 0;
event.GUIEvent.EventType = EGET_FILE_SELECTED;
Parent->OnEvent(event);
}
//! sends the event that the file choose process has been canceld
void CGUIColorSelectDialog::sendCancelEvent()
{
SEvent event;
event.EventType = EET_GUI_EVENT;
event.GUIEvent.Caller = this;
event.GUIEvent.Element = 0;
event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
Parent->OnEvent(event);
}
} // end namespace gui
} // end namespace irr