1014 lines
23 KiB
C++
1014 lines
23 KiB
C++
|
#include "widgets.h"
|
||
|
#include "main.h"
|
||
|
#include "utils.h"
|
||
|
#include "sound.h"
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Button
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
Button::Button(int x, int y, const std::wstring &name, Command *cmd,
|
||
|
bool transparent)
|
||
|
{
|
||
|
image = loadImage(name, transparent);
|
||
|
highlighted = adjustBrightness(image, 1.5, transparent);
|
||
|
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = image->w;
|
||
|
height = image->h;
|
||
|
|
||
|
mouseInside = false;
|
||
|
command = cmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
Button::Button(int x, int y, int w, int h, Font *font,
|
||
|
int fR, int fG, int fB, int hR, int hG, int hB,
|
||
|
const std::wstring &text, Command *cmd)
|
||
|
{
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = w;
|
||
|
height = h;
|
||
|
|
||
|
SDL_Surface *s = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
|
||
|
24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0/*0xFF000000*/);
|
||
|
SDL_Rect src = { x, y, width, height };
|
||
|
SDL_Rect dst = { 0, 0, width, height };
|
||
|
SDL_BlitSurface(screen.getSurface(), &src, s, &dst);
|
||
|
|
||
|
int tW, tH;
|
||
|
font->getSize(text, tW, tH);
|
||
|
font->draw(s, (width - tW) / 2, (height - tH) / 2, fR, fG, fB, true, text);
|
||
|
image = SDL_DisplayFormat(s);
|
||
|
SDL_BlitSurface(screen.getSurface(), &src, s, &dst);
|
||
|
font->draw(s, (width - tW) / 2, (height - tH) / 2, hR, hG, hB, true, text);
|
||
|
highlighted = SDL_DisplayFormat(s);
|
||
|
SDL_FreeSurface(s);
|
||
|
|
||
|
mouseInside = false;
|
||
|
command = cmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
Button::Button(int x, int y, int w, int h, Font *font,
|
||
|
int r, int g, int b, const std::wstring &bg,
|
||
|
const std::wstring &text, bool bevel, Command *cmd)
|
||
|
{
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = w;
|
||
|
height = h;
|
||
|
|
||
|
SDL_Surface *s = screen.getSurface();
|
||
|
image = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
|
||
|
s->format->BitsPerPixel, s->format->Rmask, s->format->Gmask,
|
||
|
s->format->Bmask, s->format->Amask);
|
||
|
|
||
|
SDL_Surface *tile = loadImage(bg, true);
|
||
|
SDL_Rect src = { 0, 0, tile->w, tile->h };
|
||
|
SDL_Rect dst = { 0, 0, tile->w, tile->h };
|
||
|
for (int j = 0; j < height; j += tile->h)
|
||
|
for (int i = 0; i < width; i += tile->w) {
|
||
|
dst.x = i;
|
||
|
dst.y = j;
|
||
|
SDL_BlitSurface(tile, &src, image, &dst);
|
||
|
}
|
||
|
SDL_FreeSurface(tile);
|
||
|
|
||
|
if (bevel) {
|
||
|
SDL_LockSurface(image);
|
||
|
drawBevel(image, 0, 0, width, height, false, 1);
|
||
|
drawBevel(image, 1, 1, width - 2, height - 2, true, 1);
|
||
|
SDL_UnlockSurface(image);
|
||
|
}
|
||
|
|
||
|
int tW, tH;
|
||
|
font->getSize(text, tW, tH);
|
||
|
font->draw(image, (width - tW) / 2, (height - tH) / 2, r, g, b, true, text);
|
||
|
|
||
|
highlighted = adjustBrightness(image, 1.5, false);
|
||
|
SDL_SetColorKey(image, SDL_SRCCOLORKEY, getCornerPixel(image));
|
||
|
SDL_SetColorKey(highlighted, SDL_SRCCOLORKEY, getCornerPixel(highlighted));
|
||
|
|
||
|
mouseInside = false;
|
||
|
command = cmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
Button::Button(int x, int y, int w, int h, Font *font,
|
||
|
int r, int g, int b, const std::wstring &bg,
|
||
|
const std::wstring &text, Command *cmd)
|
||
|
{
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = w;
|
||
|
height = h;
|
||
|
|
||
|
SDL_Surface *s = screen.getSurface();
|
||
|
image = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
|
||
|
s->format->BitsPerPixel, s->format->Rmask, s->format->Gmask,
|
||
|
s->format->Bmask, s->format->Amask);
|
||
|
|
||
|
SDL_Surface *tile = loadImage(bg);
|
||
|
SDL_Rect src = { 0, 0, tile->w, tile->h };
|
||
|
SDL_Rect dst = { 0, 0, tile->w, tile->h };
|
||
|
for (int j = 0; j < height; j += tile->h)
|
||
|
for (int i = 0; i < width; i += tile->w) {
|
||
|
dst.x = i;
|
||
|
dst.y = j;
|
||
|
SDL_BlitSurface(tile, &src, image, &dst);
|
||
|
}
|
||
|
SDL_FreeSurface(tile);
|
||
|
|
||
|
SDL_LockSurface(image);
|
||
|
drawBevel(image, 0, 0, width, height, false, 1);
|
||
|
drawBevel(image, 1, 1, width - 2, height - 2, true, 1);
|
||
|
SDL_UnlockSurface(image);
|
||
|
|
||
|
int tW, tH;
|
||
|
font->getSize(text, tW, tH);
|
||
|
font->draw(image, (width - tW) / 2, (height - tH) / 2, r, g, b, true, text);
|
||
|
|
||
|
highlighted = adjustBrightness(image, 1.5, false);
|
||
|
|
||
|
mouseInside = false;
|
||
|
command = cmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
Button::~Button()
|
||
|
{
|
||
|
SDL_FreeSurface(image);
|
||
|
SDL_FreeSurface(highlighted);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Button::draw()
|
||
|
{
|
||
|
if (mouseInside)
|
||
|
screen.draw(left, top, highlighted);
|
||
|
else
|
||
|
screen.draw(left, top, image);
|
||
|
screen.addRegionToUpdate(left, top, width, height);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Button::getBounds(int &l, int &t, int &w, int &h)
|
||
|
{
|
||
|
l = left;
|
||
|
t = top;
|
||
|
w = width;
|
||
|
h = height;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Button::onMouseButtonDown(int button, int x, int y)
|
||
|
{
|
||
|
if (isInRect(x, y, left, top, width, height)) {
|
||
|
sound->play(L"click.wav");
|
||
|
if (command)
|
||
|
command->doAction();
|
||
|
return true;
|
||
|
} else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Button::onMouseMove(int x, int y)
|
||
|
{
|
||
|
bool in = isInRect(x, y, left, top, width, height);
|
||
|
if (in != mouseInside) {
|
||
|
mouseInside = in;
|
||
|
draw();
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// KeyAccel
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
KeyAccel::KeyAccel(SDLKey sym, Command *cmd)
|
||
|
{
|
||
|
command = cmd;
|
||
|
key = sym;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool KeyAccel::onKeyDown(SDLKey k, unsigned char ch)
|
||
|
{
|
||
|
if (key == k) {
|
||
|
if (command)
|
||
|
command->doAction();
|
||
|
return true;
|
||
|
} else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Area
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
Area::Area()
|
||
|
{
|
||
|
timer = NULL;
|
||
|
}
|
||
|
|
||
|
Area::~Area()
|
||
|
{
|
||
|
for (WidgetsList::iterator i = widgets.begin(); i != widgets.end(); i++) {
|
||
|
Widget *w = *i;
|
||
|
if (w && w->destroyByArea() && (! notManagedWidgets.count(w)))
|
||
|
delete w;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Area::add(Widget *widget, bool managed)
|
||
|
{
|
||
|
widgets.push_back(widget);
|
||
|
if (! managed)
|
||
|
notManagedWidgets.insert(widget);
|
||
|
widget->setParent(this);
|
||
|
}
|
||
|
|
||
|
void Area::remove(Widget *widget)
|
||
|
{
|
||
|
widgets.remove(widget);
|
||
|
notManagedWidgets.insert(widget);
|
||
|
}
|
||
|
|
||
|
void Area::handleEvent(const SDL_Event &event)
|
||
|
{
|
||
|
switch (event.type) {
|
||
|
case SDL_MOUSEBUTTONDOWN:
|
||
|
for (WidgetsList::iterator i = widgets.begin(); i != widgets.end(); i++)
|
||
|
if ((*i)->onMouseButtonDown(event.button.button,
|
||
|
event.button.x, event.button.y))
|
||
|
return;
|
||
|
break;
|
||
|
|
||
|
case SDL_MOUSEBUTTONUP:
|
||
|
for (WidgetsList::iterator i = widgets.begin(); i != widgets.end(); i++)
|
||
|
if ((*i)->onMouseButtonUp(event.button.button,
|
||
|
event.button.x, event.button.y))
|
||
|
return;
|
||
|
break;
|
||
|
|
||
|
case SDL_MOUSEMOTION:
|
||
|
for (WidgetsList::iterator i = widgets.begin(); i != widgets.end(); i++)
|
||
|
if ((*i)->onMouseMove(event.motion.x, event.motion.y))
|
||
|
return;
|
||
|
break;
|
||
|
|
||
|
case SDL_VIDEOEXPOSE:
|
||
|
for (WidgetsList::iterator i = widgets.begin(); i != widgets.end(); i++)
|
||
|
(*i)->draw();
|
||
|
break;
|
||
|
|
||
|
case SDL_KEYDOWN:
|
||
|
for (WidgetsList::iterator i = widgets.begin(); i != widgets.end(); i++)
|
||
|
if ((*i)->onKeyDown(event.key.keysym.sym,
|
||
|
(unsigned char)event.key.keysym.unicode))
|
||
|
return;
|
||
|
break;
|
||
|
|
||
|
case SDL_QUIT:
|
||
|
exit(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Area::run()
|
||
|
{
|
||
|
terminate = false;
|
||
|
SDL_Event event;
|
||
|
|
||
|
Uint32 lastTimer = 0;
|
||
|
draw();
|
||
|
screen.showMouse();
|
||
|
|
||
|
bool runTimer = timer ? true : false;
|
||
|
bool dispetchEvent;
|
||
|
while (! terminate) {
|
||
|
dispetchEvent = true;
|
||
|
if (! timer) {
|
||
|
SDL_WaitEvent(&event);
|
||
|
} else {
|
||
|
Uint32 now = SDL_GetTicks();
|
||
|
if (now - lastTimer > time) {
|
||
|
lastTimer = now;
|
||
|
runTimer = true;
|
||
|
}
|
||
|
if (! SDL_PollEvent(&event)) {
|
||
|
if (! runTimer) {
|
||
|
SDL_Delay(20);
|
||
|
continue;
|
||
|
} else
|
||
|
dispetchEvent = false;
|
||
|
}
|
||
|
}
|
||
|
screen.hideMouse();
|
||
|
if (runTimer) {
|
||
|
if (timer)
|
||
|
timer->onTimer();
|
||
|
runTimer = false;
|
||
|
}
|
||
|
if (dispetchEvent)
|
||
|
handleEvent(event);
|
||
|
if (! terminate) {
|
||
|
screen.showMouse();
|
||
|
screen.flush();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Area::finishEventLoop()
|
||
|
{
|
||
|
terminate = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Area::draw()
|
||
|
{
|
||
|
for (WidgetsList::iterator i = widgets.begin(); i != widgets.end(); i++)
|
||
|
(*i)->draw();
|
||
|
}
|
||
|
|
||
|
|
||
|
void Area::setTimer(Uint32 interval, TimerHandler *t)
|
||
|
{
|
||
|
time = interval;
|
||
|
timer = t;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Area::updateMouse()
|
||
|
{
|
||
|
int x, y;
|
||
|
SDL_GetMouseState(&x, &y);
|
||
|
|
||
|
for (WidgetsList::iterator i = widgets.begin(); i != widgets.end(); i++)
|
||
|
if ((*i)->onMouseMove(x, y))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// AnyKeyAccel
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
AnyKeyAccel::AnyKeyAccel()
|
||
|
{
|
||
|
command = NULL;
|
||
|
}
|
||
|
|
||
|
AnyKeyAccel::AnyKeyAccel(Command *cmd)
|
||
|
{
|
||
|
command = cmd;
|
||
|
}
|
||
|
|
||
|
AnyKeyAccel::~AnyKeyAccel()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool AnyKeyAccel::onKeyDown(SDLKey key, unsigned char ch)
|
||
|
{
|
||
|
if (((key >= SDLK_NUMLOCK) && (key <= SDLK_COMPOSE)) ||
|
||
|
(key == SDLK_TAB) || (key == SDLK_UNKNOWN))
|
||
|
return false;
|
||
|
|
||
|
if (command)
|
||
|
command->doAction();
|
||
|
else
|
||
|
area->finishEventLoop();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool AnyKeyAccel::onMouseButtonDown(int button, int x, int y)
|
||
|
{
|
||
|
if (command)
|
||
|
command->doAction();
|
||
|
else
|
||
|
area->finishEventLoop();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Window
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
Window::Window(int x, int y, int w, int h, const std::wstring &bg,
|
||
|
bool frameWidth, bool raised)
|
||
|
{
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = w;
|
||
|
height = h;
|
||
|
|
||
|
SDL_Surface *s = screen.getSurface();
|
||
|
SDL_Surface *win = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
|
||
|
s->format->BitsPerPixel, s->format->Rmask, s->format->Gmask,
|
||
|
s->format->Bmask, s->format->Amask);
|
||
|
|
||
|
SDL_Surface *tile = loadImage(bg);
|
||
|
SDL_Rect src = { 0, 0, tile->w, tile->h };
|
||
|
SDL_Rect dst = { 0, 0, tile->w, tile->h };
|
||
|
for (int j = 0; j < height; j += tile->h)
|
||
|
for (int i = 0; i < width; i += tile->w) {
|
||
|
dst.x = i;
|
||
|
dst.y = j;
|
||
|
SDL_BlitSurface(tile, &src, win, &dst);
|
||
|
}
|
||
|
SDL_FreeSurface(tile);
|
||
|
|
||
|
SDL_LockSurface(win);
|
||
|
double k = 2.6;
|
||
|
double f = 0.1;
|
||
|
for (int i = 0; i < frameWidth; i++) {
|
||
|
double ltK, rbK;
|
||
|
if (raised) {
|
||
|
ltK = k; rbK = f;
|
||
|
} else {
|
||
|
ltK = f; rbK = k;
|
||
|
}
|
||
|
for (int j = i; j < height - i - 1; j++)
|
||
|
adjustBrightness(win, i, j, ltK);
|
||
|
for (int j = i; j < width - i; j++)
|
||
|
adjustBrightness(win, j, i, ltK);
|
||
|
for (int j = i+1; j < height - i; j++)
|
||
|
adjustBrightness(win, width - i - 1, j, rbK);
|
||
|
for (int j = i; j < width - i - 1; j++)
|
||
|
adjustBrightness(win, j, height - i - 1, rbK);
|
||
|
k -= 0.2;
|
||
|
f += 0.1;
|
||
|
}
|
||
|
SDL_UnlockSurface(win);
|
||
|
|
||
|
background = SDL_DisplayFormat(win);
|
||
|
SDL_FreeSurface(win);
|
||
|
}
|
||
|
|
||
|
|
||
|
Window::~Window()
|
||
|
{
|
||
|
SDL_FreeSurface(background);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Window::draw()
|
||
|
{
|
||
|
screen.draw(left, top, background);
|
||
|
screen.addRegionToUpdate(left, top, width, height);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Label
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
Label::Label(Font *f, int x, int y, int r, int g, int b, std::wstring s,
|
||
|
bool sh): text(s)
|
||
|
{
|
||
|
font = f;
|
||
|
left = x;
|
||
|
top = y;
|
||
|
red = r;
|
||
|
green = g;
|
||
|
blue = b;
|
||
|
hAlign = ALIGN_LEFT;
|
||
|
vAlign = ALIGN_TOP;
|
||
|
shadow = sh;
|
||
|
}
|
||
|
|
||
|
|
||
|
Label::Label(Font *f, int x, int y, int w, int h, HorAlign hA, VerAlign vA,
|
||
|
int r, int g, int b, const std::wstring &s):
|
||
|
text(s)
|
||
|
{
|
||
|
font = f;
|
||
|
left = x;
|
||
|
top = y;
|
||
|
red = r;
|
||
|
green = g;
|
||
|
blue = b;
|
||
|
hAlign = hA;
|
||
|
vAlign = vA;
|
||
|
width = w;
|
||
|
height = h;
|
||
|
shadow = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Label::draw()
|
||
|
{
|
||
|
int w, h, x, y;
|
||
|
font->getSize(text, w, h);
|
||
|
|
||
|
switch (hAlign) {
|
||
|
case ALIGN_RIGHT: x = left + width - w; break;
|
||
|
case ALIGN_CENTER: x = left + (width - w) / 2; break;
|
||
|
default: x = left;
|
||
|
}
|
||
|
|
||
|
switch (vAlign) {
|
||
|
case ALIGN_BOTTOM: y = top + height - h; break;
|
||
|
case ALIGN_MIDDLE: y = top + (height - h) / 2; break;
|
||
|
default: y = top;
|
||
|
}
|
||
|
|
||
|
font->draw(x, y, red,green,blue, shadow, text);
|
||
|
screen.addRegionToUpdate(x, y, w, h);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// InputField
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
InputField::InputField(int x, int y, int w, int h, const std::wstring &background,
|
||
|
std::wstring &s, int maxLen, int r, int g, int b, Font *f):
|
||
|
Window(x, y, w, h, background, 1, false), text(s)
|
||
|
{
|
||
|
maxLength = maxLen;
|
||
|
red = r;
|
||
|
green = g;
|
||
|
blue = b;
|
||
|
font = f;
|
||
|
moveCursor(text.length());
|
||
|
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
|
||
|
SDL_EnableUNICODE(1);
|
||
|
}
|
||
|
|
||
|
InputField::~InputField()
|
||
|
{
|
||
|
SDL_EnableKeyRepeat(0, 0);
|
||
|
}
|
||
|
|
||
|
void InputField::draw()
|
||
|
{
|
||
|
Window::draw();
|
||
|
|
||
|
SDL_Rect rect = { left+1, top+1, width-2, height-2 };
|
||
|
SDL_SetClipRect(screen.getSurface(), &rect);
|
||
|
|
||
|
font->draw(left+1, top+1, red,green,blue, true, text);
|
||
|
|
||
|
if (cursorVisible) {
|
||
|
int pos = 0;
|
||
|
if (cursorPos > 0)
|
||
|
pos += font->getWidth(text.substr(0, cursorPos));
|
||
|
for (int i = 2; i < height-2; i++) {
|
||
|
screen.setPixel(left + pos, top + i, red, green, blue);
|
||
|
screen.setPixel(left + pos + 1, top + i, red, green, blue);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SDL_SetClipRect(screen.getSurface(), NULL);
|
||
|
}
|
||
|
|
||
|
void InputField::setParent(Area *a)
|
||
|
{
|
||
|
Window::setParent(a);
|
||
|
area->setTimer(100, this);
|
||
|
}
|
||
|
|
||
|
|
||
|
void InputField::onTimer()
|
||
|
{
|
||
|
Uint32 now = SDL_GetTicks();
|
||
|
if (now - lastCursor > 1000) {
|
||
|
cursorVisible = ! cursorVisible;
|
||
|
lastCursor = now;
|
||
|
draw();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
bool InputField::onKeyDown(SDLKey key, unsigned char translatedChar)
|
||
|
{
|
||
|
switch (key) {
|
||
|
case SDLK_BACKSPACE:
|
||
|
if (cursorPos > 0) {
|
||
|
text.erase(cursorPos - 1, 1);
|
||
|
moveCursor(cursorPos - 1);
|
||
|
} else
|
||
|
moveCursor(cursorPos);
|
||
|
draw();
|
||
|
return true;
|
||
|
|
||
|
case SDLK_LEFT:
|
||
|
if (cursorPos > 0)
|
||
|
moveCursor(cursorPos - 1);
|
||
|
else
|
||
|
moveCursor(cursorPos);
|
||
|
draw();
|
||
|
return true;
|
||
|
|
||
|
case SDLK_RIGHT:
|
||
|
if (cursorPos < (int)text.length())
|
||
|
moveCursor(cursorPos + 1);
|
||
|
else
|
||
|
moveCursor(cursorPos);
|
||
|
draw();
|
||
|
return true;
|
||
|
|
||
|
case SDLK_HOME:
|
||
|
moveCursor(0);
|
||
|
draw();
|
||
|
return true;
|
||
|
|
||
|
case SDLK_END:
|
||
|
moveCursor(text.length());
|
||
|
draw();
|
||
|
return true;
|
||
|
|
||
|
case SDLK_DELETE:
|
||
|
if (cursorPos < (int)text.length())
|
||
|
text.erase(cursorPos, 1);
|
||
|
moveCursor(cursorPos);
|
||
|
draw();
|
||
|
return true;
|
||
|
|
||
|
default: ;
|
||
|
}
|
||
|
|
||
|
if (translatedChar > 31)
|
||
|
onCharTyped(translatedChar);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool InputField::onKeyUp(SDLKey key)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void InputField::onCharTyped(unsigned char ch)
|
||
|
{
|
||
|
if ((int)text.length() < maxLength) {
|
||
|
wchar_t buf[2];
|
||
|
buf[0] = ch;
|
||
|
buf[1] = 0;
|
||
|
text.insert(cursorPos, buf);
|
||
|
moveCursor(cursorPos + 1);
|
||
|
} else
|
||
|
moveCursor(cursorPos);
|
||
|
draw();
|
||
|
}
|
||
|
|
||
|
void InputField::moveCursor(int pos)
|
||
|
{
|
||
|
lastCursor = SDL_GetTicks();
|
||
|
cursorVisible = true;
|
||
|
cursorPos = pos;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Checkbox
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
Checkbox::Checkbox(int x, int y, int w, int h, Font *font,
|
||
|
int r, int g, int b, const std::wstring &bg,
|
||
|
bool &chk): checked(chk)
|
||
|
{
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = w;
|
||
|
height = h;
|
||
|
checked = chk;
|
||
|
|
||
|
SDL_Surface *s = screen.getSurface();
|
||
|
image = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
|
||
|
s->format->BitsPerPixel, s->format->Rmask, s->format->Gmask,
|
||
|
s->format->Bmask, s->format->Amask);
|
||
|
|
||
|
SDL_Surface *tile = loadImage(bg);
|
||
|
SDL_Rect src = { 0, 0, tile->w, tile->h };
|
||
|
SDL_Rect dst = { 0, 0, tile->w, tile->h };
|
||
|
for (int j = 0; j < height; j += tile->h)
|
||
|
for (int i = 0; i < width; i += tile->w) {
|
||
|
dst.x = i;
|
||
|
dst.y = j;
|
||
|
SDL_BlitSurface(tile, &src, image, &dst);
|
||
|
}
|
||
|
SDL_FreeSurface(tile);
|
||
|
|
||
|
SDL_LockSurface(image);
|
||
|
drawBevel(image, 0, 0, width, height, false, 1);
|
||
|
drawBevel(image, 1, 1, width - 2, height - 2, true, 1);
|
||
|
SDL_UnlockSurface(image);
|
||
|
|
||
|
highlighted = adjustBrightness(image, 1.5, false);
|
||
|
|
||
|
checkedImage = SDL_DisplayFormat(image);
|
||
|
int tW, tH;
|
||
|
font->getSize(L"X", tW, tH);
|
||
|
tH += 2;
|
||
|
tW += 2;
|
||
|
font->draw(checkedImage, (width - tW) / 2, (height - tH) / 2, r, g, b,
|
||
|
true, L"X");
|
||
|
checkedHighlighted = adjustBrightness(checkedImage, 1.5, false);
|
||
|
|
||
|
mouseInside = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
Checkbox::~Checkbox()
|
||
|
{
|
||
|
SDL_FreeSurface(image);
|
||
|
SDL_FreeSurface(highlighted);
|
||
|
SDL_FreeSurface(checkedImage);
|
||
|
SDL_FreeSurface(checkedHighlighted);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Checkbox::draw()
|
||
|
{
|
||
|
if (checked) {
|
||
|
if (mouseInside)
|
||
|
screen.draw(left, top, checkedHighlighted);
|
||
|
else
|
||
|
screen.draw(left, top, checkedImage);
|
||
|
} else {
|
||
|
if (mouseInside)
|
||
|
screen.draw(left, top, highlighted);
|
||
|
else
|
||
|
screen.draw(left, top, image);
|
||
|
}
|
||
|
screen.addRegionToUpdate(left, top, width, height);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Checkbox::getBounds(int &l, int &t, int &w, int &h)
|
||
|
{
|
||
|
l = left;
|
||
|
t = top;
|
||
|
w = width;
|
||
|
h = height;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Checkbox::onMouseButtonDown(int button, int x, int y)
|
||
|
{
|
||
|
if (isInRect(x, y, left, top, width, height)) {
|
||
|
sound->play(L"click.wav");
|
||
|
checked = ! checked;
|
||
|
draw();
|
||
|
return true;
|
||
|
} else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Checkbox::onMouseMove(int x, int y)
|
||
|
{
|
||
|
bool in = isInRect(x, y, left, top, width, height);
|
||
|
if (in != mouseInside) {
|
||
|
mouseInside = in;
|
||
|
draw();
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Picture
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
Picture::Picture(int x, int y, const std::wstring &name, bool transparent)
|
||
|
{
|
||
|
image = loadImage(name, transparent);
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = image->w;
|
||
|
height = image->h;
|
||
|
managed = true;
|
||
|
}
|
||
|
|
||
|
Picture::Picture(int x, int y, SDL_Surface *img)
|
||
|
{
|
||
|
image = img;
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = image->w;
|
||
|
height = image->h;
|
||
|
managed = false;
|
||
|
}
|
||
|
|
||
|
Picture::~Picture()
|
||
|
{
|
||
|
if (managed)
|
||
|
SDL_FreeSurface(image);
|
||
|
}
|
||
|
|
||
|
void Picture::draw()
|
||
|
{
|
||
|
screen.draw(left, top, image);
|
||
|
screen.addRegionToUpdate(left, top, width, height);
|
||
|
}
|
||
|
|
||
|
void Picture::moveX(const int newX)
|
||
|
{
|
||
|
left = newX;
|
||
|
}
|
||
|
|
||
|
void Picture::getBounds(int &l, int &t, int &w, int &h)
|
||
|
{
|
||
|
l = left;
|
||
|
t = top;
|
||
|
w = width;
|
||
|
h = height;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Slider
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
Slider::Slider(int x, int y, int w, int h, float &v): value(v)
|
||
|
{
|
||
|
left = x;
|
||
|
top = y;
|
||
|
width = w;
|
||
|
height = h;
|
||
|
background = NULL;
|
||
|
createSlider(height);
|
||
|
highlight = false;
|
||
|
dragging = false;
|
||
|
}
|
||
|
|
||
|
Slider::~Slider()
|
||
|
{
|
||
|
if (background)
|
||
|
SDL_FreeSurface(background);
|
||
|
if (slider)
|
||
|
SDL_FreeSurface(slider);
|
||
|
if (activeSlider)
|
||
|
SDL_FreeSurface(activeSlider);
|
||
|
}
|
||
|
|
||
|
void Slider::draw()
|
||
|
{
|
||
|
if (! background)
|
||
|
createBackground();
|
||
|
screen.draw(left, top, background);
|
||
|
screen.addRegionToUpdate(left, top, width, height);
|
||
|
int posX = valueToX(value);
|
||
|
SDL_Surface *s = highlight ? activeSlider : slider;
|
||
|
screen.draw(left + posX, top, s);
|
||
|
}
|
||
|
|
||
|
void Slider::createBackground()
|
||
|
{
|
||
|
background = screen.createSubimage(left, top, width, height);
|
||
|
int y = height / 2;
|
||
|
SDL_LockSurface(background);
|
||
|
drawBevel(background, 0, y - 2, width, 4, false, 1);
|
||
|
SDL_UnlockSurface(background);
|
||
|
}
|
||
|
|
||
|
void Slider::createSlider(int size)
|
||
|
{
|
||
|
SDL_Surface *s = screen.getSurface();
|
||
|
SDL_Surface *image = SDL_CreateRGBSurface(SDL_SWSURFACE, size, size,
|
||
|
s->format->BitsPerPixel, s->format->Rmask, s->format->Gmask,
|
||
|
s->format->Bmask, s->format->Amask);
|
||
|
|
||
|
SDL_Surface *tile = loadImage(L"blue.bmp");
|
||
|
SDL_Rect src = { 0, 0, tile->w, tile->h };
|
||
|
SDL_Rect dst = { 0, 0, tile->w, tile->h };
|
||
|
for (int j = 0; j < size; j += tile->h)
|
||
|
for (int i = 0; i < size; i += tile->w) {
|
||
|
dst.x = i;
|
||
|
dst.y = j;
|
||
|
SDL_BlitSurface(tile, &src, image, &dst);
|
||
|
}
|
||
|
SDL_FreeSurface(tile);
|
||
|
|
||
|
SDL_LockSurface(image);
|
||
|
drawBevel(image, 0, 0, size, size, false, 1);
|
||
|
drawBevel(image, 1, 1, size - 2, size - 2, true, 1);
|
||
|
SDL_UnlockSurface(image);
|
||
|
|
||
|
activeSlider = adjustBrightness(image, 1.5, false);
|
||
|
slider = SDL_DisplayFormat(image);
|
||
|
|
||
|
SDL_FreeSurface(image);
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Slider::onMouseButtonDown(int button, int x, int y)
|
||
|
{
|
||
|
bool in = isInRect(x, y, left, top, width, height);
|
||
|
if (in) {
|
||
|
int sliderX = valueToX(value);
|
||
|
bool hl = isInRect(x, y, left + sliderX, top, height, height);
|
||
|
if (hl) {
|
||
|
dragging = true;
|
||
|
dragOffsetX = x - left - sliderX;
|
||
|
}
|
||
|
}
|
||
|
return in;
|
||
|
}
|
||
|
|
||
|
bool Slider::onMouseButtonUp(int button, int x, int y)
|
||
|
{
|
||
|
if (dragging) {
|
||
|
dragging = false;
|
||
|
return true;
|
||
|
} else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
int Slider::valueToX(float value)
|
||
|
{
|
||
|
if (value < 0)
|
||
|
value = 0.0f;
|
||
|
if (value > 1)
|
||
|
value = 1.0f;
|
||
|
return (int)(((float)(width - height)) * value);
|
||
|
}
|
||
|
|
||
|
|
||
|
float Slider::xToValue(int pos)
|
||
|
{
|
||
|
if (0 > pos)
|
||
|
pos = 0;
|
||
|
if (width - height < pos)
|
||
|
pos = width - height;
|
||
|
return (float)pos / (float)(width - height);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool Slider::onMouseMove(int x, int y)
|
||
|
{
|
||
|
if (dragging) {
|
||
|
float val = xToValue(x - left - dragOffsetX);
|
||
|
if (val != value) {
|
||
|
value = val;
|
||
|
draw();
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool in = isInRect(x, y, left, top, width, height);
|
||
|
if (in) {
|
||
|
int sliderX = valueToX(value);
|
||
|
bool hl = isInRect(x, y, left + sliderX, top, height, height);
|
||
|
if (hl != highlight) {
|
||
|
highlight = hl;
|
||
|
draw();
|
||
|
}
|
||
|
} else
|
||
|
if (highlight) {
|
||
|
highlight = false;
|
||
|
draw();
|
||
|
}
|
||
|
return in;
|
||
|
}
|
||
|
|