Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PopupKeyboard] Add Korean & 4th Layout & fix Korean render bug & Unicode support for "Jump to game beginning with the letter" #1858

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions es-app/src/guis/GuiGamelistOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,29 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, IGameListView* gamelist,
{
mJumpToLetterList = std::make_shared<LetterList>(mWindow, _("JUMP TO GAME BEGINNING WITH THE LETTER"), false);

char curChar = (char)toupper(getGamelist()->getCursor()->getName()[0]);
const std::string& cursorName = getGamelist()->getCursor()->getName();
std::string curChar;

if (std::find(letters.begin(), letters.end(), std::string(1, curChar)) == letters.end())
curChar = letters.at(0)[0];
if (Utils::String::isKorean(cursorName.c_str()))
{
const char* koreanLetter = nullptr;

std::string nameChar = cursorName.substr(0, 3);
if (!Utils::String::splitHangulSyllable(nameChar.c_str(), &koreanLetter) || !koreanLetter)
curChar = std::string(letters.at(0)); // Korean supports chosung search only. set default.
else
curChar = std::string(koreanLetter, 3);
}
else
{
curChar = std::string(1, toupper(cursorName[0]));
}

for (auto letter : letters)
mJumpToLetterList->add(letter, letter[0], letter[0] == curChar);
if (std::find(letters.begin(), letters.end(), curChar) == letters.end())
curChar = letters.at(0);

for (const auto& letter : letters)
mJumpToLetterList->add(letter, letter, letter == curChar);

row.addElement(std::make_shared<TextComponent>(mWindow, _("JUMP TO GAME BEGINNING WITH THE LETTER"), theme->Text.font, theme->Text.color), true);
row.addElement(mJumpToLetterList, false);
Expand Down Expand Up @@ -487,7 +503,7 @@ void GuiGamelistOptions::openMetaDataEd()

void GuiGamelistOptions::jumpToLetter()
{
char letter = mJumpToLetterList->getSelected();
std::string letter = mJumpToLetterList->getSelected();
IGameListView* gamelist = getGamelist();

if (mListSort->getSelected() != 0)
Expand All @@ -505,11 +521,27 @@ void GuiGamelistOptions::jumpToLetter()
auto files = gamelist->getFileDataEntries();
for (int i = files.size() - 1; i >= 0; i--)
{
auto name = files.at(i)->getName();
const std::string& name = files.at(i)->getName();
if (name.empty())
continue;

char checkLetter = (char)toupper(name[0]);
std::string checkLetter;

if (Utils::String::isKorean(name.c_str()))
{
const char* koreanLetter = nullptr;

std::string nameChar = name.substr(0, 3);
if (!Utils::String::splitHangulSyllable(nameChar.c_str(), &koreanLetter) || !koreanLetter)
continue;

checkLetter = std::string(koreanLetter, 3);
}
else
{
checkLetter = std::string(1, toupper(name[0]));
}

if (letterIndex >= 0 && checkLetter != letter)
break;

Expand Down
2 changes: 1 addition & 1 deletion es-app/src/guis/GuiGamelistOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class GuiGamelistOptions : public GuiComponent

MenuComponent mMenu;

typedef OptionListComponent<char> LetterList;
typedef OptionListComponent<std::string> LetterList;
std::shared_ptr<LetterList> mJumpToLetterList;

typedef OptionListComponent<unsigned int> SortList;
Expand Down
150 changes: 89 additions & 61 deletions es-app/src/views/gamelist/ISimpleGameListView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,100 +481,128 @@ void ISimpleGameListView::moveToRandomGame()
setCursor(list.at(target));
}

bool ISimpleGameListView::moveToLetter(char letter)
bool ISimpleGameListView::moveToLetter(const std::string& letter)
{

auto files = getFileDataEntries();
long letterIndex = -1;
long letterIndex = -1;

for (int i = files.size() - 1; i >= 0; i--)
{
auto name = files.at(i)->getName();
if (name.empty())
continue;

char checkLetter = (char)toupper(name[0]);
if (letterIndex >= 0 && checkLetter != letter)
break;
{
const std::string& name = files.at(i)->getName();
if (name.empty())
continue;

if (checkLetter == letter)
letterIndex = i;
}
std::string checkLetter;

if (letterIndex >= 0) {
setCursor(files.at(letterIndex));
return 1;
}
if (Utils::String::isKorean(name.c_str()))
{
const char* koreanLetter = nullptr;

return 0;
}
std::string nameChar = name.substr(0, 3);
if (!Utils::String::splitHangulSyllable(nameChar.c_str(), &koreanLetter) || !koreanLetter)
continue; // Korean supports chosung search only.
else
checkLetter = std::string(koreanLetter, 3);
}
else
{
checkLetter = std::string(1, toupper(name[0]));
}

void ISimpleGameListView::moveToNextLetter()
{
std::vector<std::string> letters = getEntriesLetters();
if (letters.empty())
return;
if (letterIndex >= 0 && checkLetter != letter)
break;

FileData* game = getCursor();
if (game == nullptr) {
return;
if (checkLetter == letter)
letterIndex = i;
}

auto namecurrent = game->getName();
char curChar = (char)toupper(namecurrent[0]);

auto it = std::find(letters.begin(), letters.end(), std::string(1, curChar));
if (it != letters.end()) {
int index = it - letters.begin();
index++;
if (index >= letters.size())
index = 0;
char letter = letters.at(index)[0];
moveToLetter(letter);
if (letterIndex >= 0) {
setCursor(files.at(letterIndex));
return true;
}

return false;
}

void ISimpleGameListView::moveToPreviousLetter()
void ISimpleGameListView::moveToLetterByOffset(int offset)
{

std::vector<std::string> letters = getEntriesLetters();
if (letters.empty())
std::vector<std::string> letters = getEntriesLetters();
if (letters.empty())
return;

FileData* game = getCursor();
if (game == nullptr) {
if (game == nullptr)
return;
}

auto namecurrent = game->getName();
char curChar = (char)toupper(namecurrent[0]);
const std::string& namecurrent = game->getName();
std::string curLetter;

if (Utils::String::isKorean(namecurrent.c_str()))
{
const char* koreanLetter = nullptr;

auto it = std::find(letters.begin(), letters.end(), std::string(1, curChar));
if (it != letters.end()) {
int index = it - letters.begin();
index--;
std::string nameChar = namecurrent.substr(0, 3);
if (!Utils::String::splitHangulSyllable(nameChar.c_str(), &koreanLetter) || !koreanLetter)
curLetter = std::string(letters.at(0)); // Korean supports chosung search only. set default.
else
curLetter = std::string(koreanLetter, 3);
}
else
{
curLetter = std::string(1, toupper(namecurrent[0]));
}

auto it = std::find(letters.begin(), letters.end(), curLetter);
if (it != letters.end())
{
int index = std::distance(letters.begin(), it) + offset;
if (index < 0)
index = letters.size()-1;
index = letters.size() - 1;
else if (index >= letters.size())
index = 0;

char letter = letters.at(index)[0];
moveToLetter(letter);
moveToLetter(letters.at(index));
}
}

void ISimpleGameListView::moveToNextLetter()
{
moveToLetterByOffset(1);
}

void ISimpleGameListView::moveToPreviousLetter()
{
moveToLetterByOffset(-1);
}

std::vector<std::string> ISimpleGameListView::getEntriesLetters()
{
std::set<std::string> setOfLetters;

for (auto file : getFileDataEntries())
if (file->getType() == GAME)
setOfLetters.insert(std::string(1, toupper(file->getName()[0])));
for (auto file : getFileDataEntries())
{
if (file->getType() != GAME)
continue;

const std::string& name = file->getName();

if (Utils::String::isKorean(name.c_str()))
{
const char* koreanLetter = nullptr;

std::vector<std::string> letters;
std::string nameChar = name.substr(0, 3);
if (!Utils::String::splitHangulSyllable(nameChar.c_str(), &koreanLetter) || !koreanLetter)
continue;

for (const auto letter : setOfLetters)
letters.push_back(letter);
setOfLetters.insert(std::string(koreanLetter, 3));
}
else
{
setOfLetters.insert(std::string(1, toupper(name[0])));
}
}

std::sort(letters.begin(), letters.end());
std::vector<std::string> letters(setOfLetters.begin(), setOfLetters.end());
return letters;
}

Expand Down
3 changes: 2 additions & 1 deletion es-app/src/views/gamelist/ISimpleGameListView.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class ISimpleGameListView : public IGameListView
void closePopupContext();

virtual void moveToRandomGame();
virtual bool moveToLetter(char letter);
virtual bool moveToLetter(const std::string& letter);
virtual void moveToLetterByOffset(int offset);
virtual void moveToNextLetter();
virtual void moveToPreviousLetter();

Expand Down
16 changes: 11 additions & 5 deletions es-core/src/components/TextEditComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,26 @@ std::string TextEditComponent::getValue() const

void TextEditComponent::textInput(const char* text)
{
if(mEditing)
if (mEditing)
{
mCursorRepeatDir = 0;
if(text[0] == '\b')
if (text[0] == '\b')
{
if(mCursor > 0)
if (mCursor > 0)
{
size_t newCursor = Utils::String::prevCursor(mText, mCursor);
mText.erase(mText.begin() + newCursor, mText.begin() + mCursor);
mCursor = (unsigned int)newCursor;
}
}else{
}
else if (mCursor > 2 && Utils::String::isKorean(text) && Utils::String::isKorean(mText.substr(mCursor - 3, 3).c_str()))
{
Utils::String::koreanTextInput(text, mText, mCursor);
}
else {
mText.insert(mCursor, text);
mCursor += (unsigned int)strlen(text);
size_t newCursor = Utils::String::nextCursor(mText, mCursor);
mCursor = (unsigned int)newCursor;
}
}

Expand Down
Loading