Skip to content
Permalink
Browse files

Merge pull request #12253 from unknownbrackets/ui-hostname

Cleanup UI hostname entry
  • Loading branch information...
unknownbrackets committed Aug 18, 2019
2 parents 044dd03 + 30dcc2a commit 4e3e00302b73bc9514ad4d1a157446a05c2a5e07
Showing with 177 additions and 137 deletions.
  1. +123 −115 UI/GameSettingsScreen.cpp
  2. +45 −18 UI/GameSettingsScreen.h
  3. +7 −3 ext/native/ui/ui_screen.cpp
  4. +2 −1 ext/native/ui/ui_screen.h
@@ -22,6 +22,7 @@
#include "base/colorutil.h"
#include "base/timeutil.h"
#include "math/curves.h"
#include "net/resolve.h"
#include "gfx_es2/gpu_features.h"
#include "gfx_es2/draw_buffer.h"
#include "i18n/i18n.h"
@@ -625,13 +626,7 @@ void GameSettingsScreen::CreateViews() {
networkingSettings->Add(new CheckBox(&g_Config.bEnableWlan, n->T("Enable networking", "Enable networking/wlan (beta)")));
networkingSettings->Add(new CheckBox(&g_Config.bDiscordPresence, n->T("Send Discord Presence information")));

#if !defined(MOBILE_DEVICE)
networkingSettings->Add(new PopupTextInputChoice(&g_Config.proAdhocServer, n->T("Change proAdhocServer Address"), "", 255, screenManager()));
#elif defined(__ANDROID__)
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.proAdhocServer, n->T("Change proAdhocServer Address"), (const char *)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeproAdhocServerAddress);
#else
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.proAdhocServer, n->T("Change proAdhocServer Address"), (const char *)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeproAdhocServerAddress);
#endif
networkingSettings->Add(new CheckBox(&g_Config.bEnableAdhocServer, n->T("Enable built-in PRO Adhoc Server", "Enable built-in PRO Adhoc Server")));
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sMACAddress, n->T("Change Mac Address"), (const char *)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeMacAddress);
networkingSettings->Add(new PopupSliderChoice(&g_Config.iPortOffset, 0, 60000, n->T("Port offset", "Port offset(0 = PSP compatibility)"), 100, screenManager()));
@@ -1203,24 +1198,12 @@ UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) {
}

UI::EventReturn GameSettingsScreen::OnChangeproAdhocServerAddress(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
if (!g_Config.bFullScreen) {
const size_t name_len = 256;

char name[name_len];
memset(name, 0, sizeof(name));
I18NCategory *sy = GetI18NCategory("System");

if (System_InputBoxGetString("Enter an IP address", g_Config.proAdhocServer.c_str(), name, name_len)) {
std::string stripped = StripSpaces(name);
g_Config.proAdhocServer = stripped;
}
}
else
screenManager()->push(new ProAdhocServerScreen);
#elif defined(__ANDROID__)
#if defined(__ANDROID__)
System_SendMessage("inputbox", ("IP:" + g_Config.proAdhocServer).c_str());
#else
screenManager()->push(new ProAdhocServerScreen);
screenManager()->push(new HostnameSelectScreen(&g_Config.proAdhocServer, sy->T("proAdhocServer Address:")));
#endif

return UI::EVENT_DONE;
@@ -1482,130 +1465,156 @@ void DeveloperToolsScreen::update() {
canAllowDebugger_ = !WebServerStopping(WebServerFlags::DEBUGGER);
}

void ProAdhocServerScreen::CreateViews() {
void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
I18NCategory *sy = GetI18NCategory("System");
I18NCategory *di = GetI18NCategory("Dialog");
I18NCategory *n = GetI18NCategory("Networking");

tempProAdhocServer = g_Config.proAdhocServer;
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));

leftColumn->Add(new ItemHeader(sy->T("proAdhocServer Address:")));
addrView_ = new TextView(tempProAdhocServer, ALIGN_LEFT, false);
leftColumn->Add(addrView_);
LinearLayout *rightColumn = new LinearLayout(ORIENT_HORIZONTAL, new AnchorLayoutParams(0, 120, 10, NONE, NONE,10));
rightColumn->Add(new Button("0"))->OnClick.Handle(this, &ProAdhocServerScreen::On0Click);
rightColumn->Add(new Button("1"))->OnClick.Handle(this, &ProAdhocServerScreen::On1Click);
rightColumn->Add(new Button("2"))->OnClick.Handle(this, &ProAdhocServerScreen::On2Click);
rightColumn->Add(new Button("3"))->OnClick.Handle(this, &ProAdhocServerScreen::On3Click);
rightColumn->Add(new Button("4"))->OnClick.Handle(this, &ProAdhocServerScreen::On4Click);
rightColumn->Add(new Button("5"))->OnClick.Handle(this, &ProAdhocServerScreen::On5Click);
rightColumn->Add(new Button("6"))->OnClick.Handle(this, &ProAdhocServerScreen::On6Click);
rightColumn->Add(new Button("7"))->OnClick.Handle(this, &ProAdhocServerScreen::On7Click);
rightColumn->Add(new Button("8"))->OnClick.Handle(this, &ProAdhocServerScreen::On8Click);
rightColumn->Add(new Button("9"))->OnClick.Handle(this, &ProAdhocServerScreen::On9Click);
rightColumn->Add(new Button("."))->OnClick.Handle(this, &ProAdhocServerScreen::OnPointClick);
rightColumn->Add(new Button(di->T("Delete")))->OnClick.Handle(this, &ProAdhocServerScreen::OnDeleteClick);
rightColumn->Add(new Button(di->T("Delete all")))->OnClick.Handle(this, &ProAdhocServerScreen::OnDeleteAllClick);
rightColumn->Add(new Button(di->T("OK")))->OnClick.Handle(this, &ProAdhocServerScreen::OnOKClick);
rightColumn->Add(new Button(di->T("Cancel")))->OnClick.Handle(this, &ProAdhocServerScreen::OnCancelClick);
root_->Add(leftColumn);
root_->Add(rightColumn);
}

UI::EventReturn ProAdhocServerScreen::On0Click(UI::EventParams &e) {
if (tempProAdhocServer.length() > 0)
tempProAdhocServer.append("0");
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
}
LinearLayout *valueRow = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, Margins(0, 0, 0, 10)));

UI::EventReturn ProAdhocServerScreen::On1Click(UI::EventParams &e) {
tempProAdhocServer.append("1");
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
}
addrView_ = new TextEdit(*value_, "");
addrView_->SetTextAlign(FLAG_DYNAMIC_ASCII);
valueRow->Add(addrView_);
parent->Add(valueRow);

UI::EventReturn ProAdhocServerScreen::On2Click(UI::EventParams &e) {
tempProAdhocServer.append("2");
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
}
LinearLayout *buttonsRow1 = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
LinearLayout *buttonsRow2 = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
parent->Add(buttonsRow1);
parent->Add(buttonsRow2);

UI::EventReturn ProAdhocServerScreen::On3Click(UI::EventParams &e) {
tempProAdhocServer.append("3");
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
}
buttonsRow1->Add(new Spacer(new LinearLayoutParams(1.0, G_LEFT)));
for (char c = '0'; c <= '9'; ++c) {
char label[] = { c, '\0' };
auto button = buttonsRow1->Add(new Button(label));
button->OnClick.Handle(this, &HostnameSelectScreen::OnNumberClick);
button->SetTag(label);
}
buttonsRow1->Add(new Button("."))->OnClick.Handle(this, &HostnameSelectScreen::OnPointClick);
buttonsRow1->Add(new Spacer(new LinearLayoutParams(1.0, G_RIGHT)));

UI::EventReturn ProAdhocServerScreen::On4Click(UI::EventParams &e) {
tempProAdhocServer.append("4");
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
buttonsRow2->Add(new Spacer(new LinearLayoutParams(1.0, G_LEFT)));
buttonsRow2->Add(new Button(di->T("Delete")))->OnClick.Handle(this, &HostnameSelectScreen::OnDeleteClick);
buttonsRow2->Add(new Button(di->T("Delete all")))->OnClick.Handle(this, &HostnameSelectScreen::OnDeleteAllClick);
buttonsRow2->Add(new Spacer(new LinearLayoutParams(1.0, G_RIGHT)));

errorView_ = parent->Add(new TextView(n->T("Invalid IP or hostname"), ALIGN_HCENTER, false, new LinearLayoutParams(Margins(0, 10, 0, 0))));
errorView_->SetTextColor(0xFF3030FF);
errorView_->SetVisibility(V_GONE);

progressView_ = parent->Add(new TextView(n->T("Validating address..."), ALIGN_HCENTER, false, new LinearLayoutParams(Margins(0, 10, 0, 0))));
progressView_->SetVisibility(V_GONE);
}

UI::EventReturn ProAdhocServerScreen::On5Click(UI::EventParams &e) {
tempProAdhocServer.append("5");
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
void HostnameSelectScreen::SendEditKey(int keyCode, int flags) {
auto oldView = UI::GetFocusedView();
UI::SetFocusedView(addrView_);
KeyInput fakeKey{ DEVICE_ID_KEYBOARD, keyCode, KEY_DOWN | flags };
addrView_->Key(fakeKey);
UI::SetFocusedView(oldView);
}

UI::EventReturn ProAdhocServerScreen::On6Click(UI::EventParams &e) {
tempProAdhocServer.append("6");
addrView_->SetText(tempProAdhocServer);
UI::EventReturn HostnameSelectScreen::OnNumberClick(UI::EventParams &e) {
std::string text = e.v ? e.v->Tag() : "";
if (text.length() == 1 && text[0] >= '0' && text[0] <= '9') {
SendEditKey(text[0], KEY_CHAR);
}
return UI::EVENT_DONE;
}

UI::EventReturn ProAdhocServerScreen::On7Click(UI::EventParams &e) {
tempProAdhocServer.append("7");
addrView_->SetText(tempProAdhocServer);
UI::EventReturn HostnameSelectScreen::OnPointClick(UI::EventParams &e) {
SendEditKey('.', KEY_CHAR);
return UI::EVENT_DONE;
}

UI::EventReturn ProAdhocServerScreen::On8Click(UI::EventParams &e) {
tempProAdhocServer.append("8");
addrView_->SetText(tempProAdhocServer);
UI::EventReturn HostnameSelectScreen::OnDeleteClick(UI::EventParams &e) {
SendEditKey(NKCODE_DEL);
return UI::EVENT_DONE;
}

UI::EventReturn ProAdhocServerScreen::On9Click(UI::EventParams &e) {
tempProAdhocServer.append("9");
addrView_->SetText(tempProAdhocServer);
UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) {
addrView_->SetText("");
return UI::EVENT_DONE;
}

void HostnameSelectScreen::ResolverThread() {
std::unique_lock<std::mutex> guard(resolverLock_);

UI::EventReturn ProAdhocServerScreen::OnPointClick(UI::EventParams &e) {
if (tempProAdhocServer.length() > 0 && tempProAdhocServer.at(tempProAdhocServer.length() - 1) != '.')
tempProAdhocServer.append(".");
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
}
while (resolverState_ != ResolverState::QUIT) {
resolverCond_.wait(guard);

UI::EventReturn ProAdhocServerScreen::OnDeleteClick(UI::EventParams &e) {
if (tempProAdhocServer.length() > 0)
tempProAdhocServer.erase(tempProAdhocServer.length() -1, 1);
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
}
if (resolverState_ == ResolverState::QUEUED) {
resolverState_ = ResolverState::PROGRESS;

UI::EventReturn ProAdhocServerScreen::OnDeleteAllClick(UI::EventParams &e) {
tempProAdhocServer = "";
addrView_->SetText(tempProAdhocServer);
return UI::EVENT_DONE;
addrinfo *resolved = nullptr;
std::string err;
toResolveResult_ = net::DNSResolve(toResolve_, "80", &resolved, err);
if (resolved)
net::DNSResolveFree(resolved);

resolverState_ = ResolverState::READY;
}
}
}

UI::EventReturn ProAdhocServerScreen::OnOKClick(UI::EventParams &e) {
g_Config.proAdhocServer = StripSpaces(tempProAdhocServer);
UIScreen::OnBack(e);
return UI::EVENT_DONE;
bool HostnameSelectScreen::CanComplete(DialogResult result) {
if (result != DR_OK)
return true;

std::string value = addrView_->GetText();
if (lastResolved_ == value) {
return true;
}

// Currently running.
if (resolverState_ == ResolverState::PROGRESS)
return false;

std::lock_guard<std::mutex> guard(resolverLock_);
switch (resolverState_) {
case ResolverState::PROGRESS:
case ResolverState::QUIT:
return false;

case ResolverState::QUEUED:
case ResolverState::WAITING:
break;

case ResolverState::READY:
if (toResolve_ == value) {
// Reset the state, nothing there now.
resolverState_ = ResolverState::WAITING;
toResolve_.clear();
lastResolved_ = value;
lastResolvedResult_ = toResolveResult_;

if (lastResolvedResult_) {
errorView_->SetVisibility(UI::V_GONE);
} else {
errorView_->SetVisibility(UI::V_VISIBLE);
}
progressView_->SetVisibility(UI::V_GONE);

return true;
}

// Throw away that last result, it was for a different value.
break;
}

resolverState_ = ResolverState::QUEUED;
toResolve_ = value;
resolverCond_.notify_one();

progressView_->SetVisibility(UI::V_VISIBLE);
errorView_->SetVisibility(UI::V_GONE);

return false;
}

UI::EventReturn ProAdhocServerScreen::OnCancelClick(UI::EventParams &e) {
tempProAdhocServer = g_Config.proAdhocServer;
UIScreen::OnBack(e);
return UI::EVENT_DONE;
void HostnameSelectScreen::OnCompleted(DialogResult result) {
if (result == DR_OK)
*value_ = addrView_->GetText();
}

SettingInfoMessage::SettingInfoMessage(int align, UI::AnchorLayoutParams *lp)
@@ -1614,7 +1623,6 @@ SettingInfoMessage::SettingInfoMessage(int align, UI::AnchorLayoutParams *lp)
SetSpacing(0.0f);
Add(new UI::Spacer(10.0f));
text_ = Add(new UI::TextView("", align, false, new LinearLayoutParams(1.0, Margins(0, 10))));
text_->SetTag("TEST?");
Add(new UI::Spacer(10.0f));
}

@@ -18,6 +18,9 @@
#pragma once

#include "ppsspp_config.h"
#include <condition_variable>
#include <mutex>
#include <thread>
#include "ui/ui_screen.h"
#include "UI/MiscScreens.h"

@@ -175,29 +178,53 @@ class DeveloperToolsScreen : public UIDialogScreenWithBackground {
bool canAllowDebugger_ = true;
};

class ProAdhocServerScreen : public UIDialogScreenWithBackground {
class HostnameSelectScreen : public PopupScreen {
public:
ProAdhocServerScreen() {}
HostnameSelectScreen(std::string *value, const std::string &title)
: PopupScreen(title, "OK", "Cancel"), value_(value) {
resolver_ = std::thread([](HostnameSelectScreen *thiz) {
thiz->ResolverThread();
}, this);
}
~HostnameSelectScreen() {
resolverState_ = ResolverState::QUIT;
resolverCond_.notify_one();
resolver_.join();
}

void CreatePopupContents(UI::ViewGroup *parent) override;

protected:
void CreateViews() override;
void OnCompleted(DialogResult result) override;
bool CanComplete(DialogResult result) override;

private:
std::string tempProAdhocServer;
UI::TextView *addrView_;
UI::EventReturn On0Click(UI::EventParams &e);
UI::EventReturn On1Click(UI::EventParams &e);
UI::EventReturn On2Click(UI::EventParams &e);
UI::EventReturn On3Click(UI::EventParams &e);
UI::EventReturn On4Click(UI::EventParams &e);
UI::EventReturn On5Click(UI::EventParams &e);
UI::EventReturn On6Click(UI::EventParams &e);
UI::EventReturn On7Click(UI::EventParams &e);
UI::EventReturn On8Click(UI::EventParams &e);
UI::EventReturn On9Click(UI::EventParams &e);
private:
void ResolverThread();
void SendEditKey(int keyCode, int flags = 0);
UI::EventReturn OnNumberClick(UI::EventParams &e);
UI::EventReturn OnPointClick(UI::EventParams &e);
UI::EventReturn OnDeleteClick(UI::EventParams &e);
UI::EventReturn OnDeleteAllClick(UI::EventParams &e);
UI::EventReturn OnOKClick(UI::EventParams &e);
UI::EventReturn OnCancelClick(UI::EventParams &e);

enum class ResolverState {
WAITING,
QUEUED,
PROGRESS,
READY,
QUIT,
};

std::string *value_;
UI::TextEdit *addrView_ = nullptr;
UI::TextView *errorView_ = nullptr;
UI::TextView *progressView_ = nullptr;

std::thread resolver_;
ResolverState resolverState_ = ResolverState::WAITING;
std::mutex resolverLock_;
std::condition_variable resolverCond_;
std::string toResolve_ = "";
bool toResolveResult_ = false;
std::string lastResolved_ = "";
bool lastResolvedResult_ = false;
};

0 comments on commit 4e3e003

Please sign in to comment.
You can’t perform that action at this time.