Files
wagic/projects/mtg/src/SimplePad.cpp

435 lines
11 KiB
C++

#include "PrecompiledHeader.h"
#include "SimplePad.h"
#include "JTypes.h"
#include "GameApp.h"
#include "Translate.h"
#define ALPHA_COLUMNS 8
#define ALPHA_ROWS 8
#define KPD_UP 0
#define KPD_DOWN 1
#define KPD_LEFT 2
#define KPD_RIGHT 3
SimpleKey::SimpleKey(string _ds, int _id)
{
displayValue = _ds;
id = _id;
for (int x = 0; x < 4; x++)
adjacency[x] = KPD_NOWHERE;
}
void SimplePad::linkKeys(int from, int to, int dir)
{
if (keys[from] && keys[to])
{
keys[from]->adjacency[dir] = to;
switch (dir)
{
case KPD_UP:
case KPD_LEFT:
dir++;
break;
default:
dir--;
}
keys[to]->adjacency[dir] = from;
}
}
SimplePad::SimplePad()
{
nbitems = 0;
bActive = false;
selected = 0;
priorKey = 0;
cursor = 0;
bShowCancel = false;
bShowNumpad = false;
bCapslock = true;
char buf[2];
buf[1] = '\0';
SimpleKey * k;
for (int x = 0; x < KPD_MAX; x++)
keys[x] = NULL;
//Add the alphabet. We cheat a bit here.
for (int x = 'a'; x <= 'z'; x++)
{
buf[0] = x;
k = Add(buf, x);
int idx = x - 'a';
if (idx > KPD_A) k->adjacency[KPD_LEFT] = idx - 1;
if (idx < KPD_Z) k->adjacency[KPD_RIGHT] = idx + 1;
if (idx > ALPHA_COLUMNS)
k->adjacency[KPD_UP] = idx - 1 - ALPHA_COLUMNS;
else
k->adjacency[KPD_UP] = KPD_INPUT;
if (idx < 25 - ALPHA_COLUMNS) k->adjacency[KPD_DOWN] = idx + 1 + ALPHA_COLUMNS;
}
Add(_("Spacebar"), KPD_SPACE);
for (int x = 25 - ALPHA_COLUMNS; x < 26; x++)
keys[x]->adjacency[KPD_DOWN] = KPD_SPACE;
k = Add(_("Confirm"), KPD_OK);
keys[KPD_Z]->adjacency[KPD_RIGHT] = KPD_OK;
k->adjacency[KPD_UP] = KPD_CAPS;
k->adjacency[KPD_LEFT] = KPD_Z;
k->adjacency[KPD_DOWN] = KPD_CANCEL;
k = Add(_("Cancel"), KPD_CANCEL);
k->adjacency[KPD_UP] = KPD_OK;
k->adjacency[KPD_LEFT] = KPD_SPACE;
k = Add(_("Del"), KPD_DEL);
keys[KPD_I]->adjacency[KPD_RIGHT] = KPD_DEL;
k->adjacency[KPD_UP] = KPD_9;
k->adjacency[KPD_DOWN] = KPD_CAPS;
k->adjacency[KPD_LEFT] = KPD_I;
k = Add(_("Caps"), KPD_CAPS);
keys[KPD_R]->adjacency[KPD_RIGHT] = KPD_CAPS;
keys[KPD_R]->adjacency[KPD_DOWN] = KPD_Z;
k->adjacency[KPD_UP] = KPD_DEL;
k->adjacency[KPD_DOWN] = KPD_OK;
k->adjacency[KPD_LEFT] = KPD_R;
for (int x = 0; x < 10; x++)
{
buf[0] = '0' + x;
Add(buf, KPD_0 + x);
if (x < 8) linkKeys(KPD_0 + x, KPD_A + x, KPD_DOWN);
if (x > 0) linkKeys(KPD_0 + x, KPD_0 + x - 1, KPD_LEFT);
}
keys[KPD_8]->adjacency[KPD_DOWN] = KPD_DEL;
keys[KPD_9]->adjacency[KPD_DOWN] = KPD_DEL;
keys[KPD_0]->adjacency[KPD_LEFT] = KPD_NOWHERE;
keys[KPD_A]->adjacency[KPD_LEFT] = KPD_NOWHERE;
keys[KPD_J]->adjacency[KPD_LEFT] = KPD_NOWHERE;
keys[KPD_S]->adjacency[KPD_LEFT] = KPD_NOWHERE;
}
SimplePad::~SimplePad()
{
for (int x = 0; x < KPD_MAX; x++)
SAFE_DELETE(keys[x]);
}
SimpleKey * SimplePad::Add(string display, unsigned char id)
{
if (nbitems >= KPD_MAX) return NULL;
keys[nbitems++] = NEW SimpleKey(display, id);
return keys[nbitems - 1];
}
void SimplePad::pressKey(unsigned char key)
{
string input = "";
if (isalpha(key))
{
if (bCapslock)
input += toupper(key);
else
input += key;
if (cursor < buffer.size()) cursor++;
buffer.insert(cursor, input);
//Auto swap capitalization
if (bCapslock && buffer.size() == 1) bCapslock = !bCapslock;
}
else if (key == KPD_SPACE)
{
if (cursor < buffer.size()) cursor++;
buffer.insert(cursor, " ");
}
else if (key == KPD_CAPS)
bCapslock = !bCapslock;
else if (key == KPD_DEL)
{
if (!buffer.size()) return;
if (cursor >= buffer.size())
{
cursor = buffer.size();
buffer = buffer.substr(0, cursor - 1);
}
else
buffer = buffer.substr(0, cursor) + buffer.substr(cursor + 1);
cursor--;
}
else if (key == KPD_OK)
Finish();
else if (key == KPD_CANCEL)
{
bCanceled = true;
Finish();
}
}
void SimplePad::MoveSelection(unsigned char moveto)
{
if (!bShowNumpad && moveto >= KPD_0 && moveto <= KPD_9)
moveto = KPD_INPUT;
else if (!bShowCancel && moveto == KPD_CANCEL) moveto = KPD_SPACE;
if (selected < KPD_MAX && selected >= 0) priorKey = selected;
if (moveto < KPD_MAX)
selected = moveto;
else if (moveto == KPD_INPUT) selected = KPD_INPUT;
}
void SimplePad::Update(float dt)
{
JGE * mEngine = JGE::GetInstance();
JButton key = mEngine->ReadButton();
//Start button changes capslock setting.
if (key == JGE_BTN_MENU)
{
if (selected != KPD_OK)
selected = KPD_OK;
else
Finish();
}
else if (key == JGE_BTN_CTRL) bCapslock = !bCapslock;
if (selected == KPD_SPACE)
{
if (bShowCancel && mEngine->GetButtonClick(JGE_BTN_RIGHT))
selected = KPD_CANCEL;
else if (key == JGE_BTN_LEFT || key == JGE_BTN_RIGHT || key == JGE_BTN_UP || key == JGE_BTN_DOWN) selected = priorKey;
} //Moving within/from the text field.
else if (selected == KPD_INPUT)
{
if (key == JGE_BTN_DOWN) selected = priorKey;
if (key == JGE_BTN_LEFT && cursor > 0)
cursor--;
else if (key == JGE_BTN_RIGHT && cursor < buffer.size()) cursor++;
}
else if (selected >= 0 && keys[selected])
{
if (key == JGE_BTN_LEFT)
MoveSelection(keys[selected]->adjacency[KPD_LEFT]);
else if (key == JGE_BTN_RIGHT) MoveSelection(keys[selected]->adjacency[KPD_RIGHT]);
if (key == JGE_BTN_DOWN)
MoveSelection(keys[selected]->adjacency[KPD_DOWN]);
else if (key == JGE_BTN_UP) MoveSelection(keys[selected]->adjacency[KPD_UP]);
}
//These bits require a valid key...
if (selected >= 0 && selected < nbitems && keys[selected]) if (key == JGE_BTN_OK) pressKey(keys[selected]->id);
if (buffer.size() > 0 && key == JGE_BTN_SEC) buffer = buffer.substr(0, buffer.size() - 1);
if (buffer.size() && key == JGE_BTN_PREV)
{
if (cursor > 0) cursor--;
}
else if (key == JGE_BTN_NEXT)
{
if (cursor < buffer.size())
cursor++;
else
{
buffer += ' ';
cursor = buffer.size();
}
}
mX = 50;
mY = 50;
//Clear input buffer.
mEngine->ResetInput();
}
void SimplePad::Start(string value, string * _dest)
{
bActive = true;
bCanceled = false;
buffer = value;
original = buffer;
dest = _dest;
cursor = buffer.size();
//Clear input buffer.
JGE * mEngine = JGE::GetInstance();
mEngine->ResetInput();
}
string SimplePad::Finish()
{
bActive = false;
//Clear input buffer.
JGE * mEngine = JGE::GetInstance();
mEngine->ResetInput();
//Return result.
if (bCanceled)
{
dest = NULL;
return original;
}
else
{ //Strip trailing spaces.
string whitespaces(" \t\f\v\n\r");
size_t found = buffer.find_last_not_of(whitespaces);
if (found != string::npos)
buffer.erase(found + 1);
else
buffer = "";
}
if (dest != NULL)
{
dest->clear();
dest->insert(0, buffer);
dest = NULL;
}
return buffer;
}
void SimplePad::Render()
{
//This could use some cleaning up to make margins more explicit
WFont * mFont = resources.GetWFont(Fonts::MENU_FONT);
float offX = 0, offY = 0;
float kH = mFont->GetHeight();
float hSpacing = mFont->GetStringWidth("W");
float rowLen = mFont->GetStringWidth("JKLMNOPQR") + 14 * 7;
float vSpacing = 0;
float kW = hSpacing;
JRenderer * renderer = JRenderer::GetInstance();
vSpacing = kH + 8;
offY = vSpacing;
if (bShowNumpad) offY += kH + 14;
//Draw Keypad Background.
renderer->FillRoundRect(mX - kW, mY - kH, (kW + 12) * 13, (kH + 14) * 5 + offY, 2, ARGB(180,0,0,0));
offY = vSpacing;
//Draw text entry bubble
renderer->FillRoundRect(mX - kW / 2, mY + offY, (kW + 12) * 11 + kW / 2, kH, 2, ARGB(255,255,255,255));
//Draw text-entry title, if we've got one.
if (title != "")
{
mFont->DrawString(_(title.c_str()), mX, mY);
}
mY += kH + 12;
//Draw cursor.
if (cursor < buffer.size())
{
kW = mFont->GetStringWidth(buffer.substr(cursor, 1).c_str());
renderer->FillRoundRect(mX + mFont->GetStringWidth(buffer.substr(0, cursor).c_str()), mY + kH - 4, kW, 4, 2,
ARGB(150,150,150,0));
}
else
{
cursor = buffer.size();
renderer->FillRoundRect(mX + mFont->GetStringWidth(buffer.substr(0, cursor).c_str()), mY + kH - 4, kW, 4, 2,
ARGB(150,150,150,0));
}
mFont->SetColor(ARGB(255,0,0,0));
mFont->DrawString(buffer.c_str(), mX, mY);
offY += kH + 12;
if (!bShowNumpad) vSpacing -= kH + 12;
for (int x = 0; x < nbitems; x++)
if (keys[x])
{
if ((x == KPD_CANCEL && !bShowCancel) || (x >= KPD_0 && x <= KPD_9 && !bShowNumpad)) continue;
switch (x)
{
case KPD_0:
offX = 0;
offY = vSpacing;
break;
case KPD_A:
offX = 0;
offY = vSpacing + (kH + 12) * 1;
break;
case KPD_J:
offX = 0;
offY = vSpacing + (kH + 12) * 2;
break;
case KPD_S:
offX = 0;
offY = vSpacing + (kH + 12) * 3;
break;
case KPD_SPACE:
offX = 0;
offY = vSpacing + (kH + 12) * 4;
break;
case KPD_OK:
offX = rowLen + hSpacing;
offY = vSpacing + (kH + 12) * 3;
break;
case KPD_CANCEL:
offX = rowLen + hSpacing;
offY = vSpacing + (kH + 12) * 4;
break;
case KPD_DEL:
offX = rowLen + hSpacing;
offY = vSpacing + (kH + 12) * 1;
break;
case KPD_CAPS:
offX = rowLen + hSpacing;
offY = vSpacing + (kH + 12) * 2;
break;
}
kW = mFont->GetStringWidth(keys[x]->displayValue.c_str());
//Render a key.
if (x != selected)
{
renderer->FillRoundRect(mX + offX - 4, mY + offY - 4, kW + 8, kH + 4, 2, ARGB(180,50,50,50));
mFont->SetColor(ARGB(255,255,255,0));
}
else
{
renderer->FillRoundRect(mX + offX - 4, mY + offY - 4, kW + 8, kH + 4, 2, ARGB(255,100,100,100));
mFont->SetColor(ARGB(255,255,255,255));
}
char vkey[2];
vkey[1] = '\0';
vkey[0] = keys[x]->id;
if (isalpha(vkey[0]))
{
if (bCapslock) vkey[0] = toupper(vkey[0]);
mFont->DrawString(vkey, mX + offX, mY + offY);
}
else
mFont->DrawString(keys[x]->displayValue.c_str(), mX + offX, mY + offY);
offX += kW + 14;
}
}
unsigned int SimplePad::cursorPos()
{
if (cursor > buffer.size()) return buffer.size();
return cursor;
}