Skip to content

Commit

Permalink
Merge pull request #17611 from hrydgard/text-input-cleanup
Browse files Browse the repository at this point in the history
Text input: Have PopupTextInputChoice use native text input if available
  • Loading branch information
hrydgard authored Jun 22, 2023
2 parents d35c172 + a17710a commit a56f74c
Show file tree
Hide file tree
Showing 19 changed files with 163 additions and 110 deletions.
10 changes: 8 additions & 2 deletions Common/System/Request.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,13 @@ const char *RequestTypeAsString(SystemRequestType type);
extern RequestManager g_requestManager;

// Wrappers for easy requests.
// NOTE: Semantics have changed - this no longer calls the callback on cancellation.
// NOTE: Semantics have changed - this no longer calls the callback on cancellation, instead you
// can specify a different callback for that.
inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, failedCallback, title, defaultValue, 0);
}

// This one will pop up a special image brwoser if available. You can also pick
// This one will pop up a special image browser if available. You can also pick
// images with the file browser below.
inline void System_BrowseForImage(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, failedCallback, title, "", 0);
Expand All @@ -99,6 +100,11 @@ inline void System_BrowseForFolder(const std::string &title, RequestCallback cal
g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, failedCallback, title, "", 0);
}

// The returned string is username + '\n' + password.
inline void System_AskUsernamePassword(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::ASK_USERNAME_PASSWORD, callback, failedCallback, title, "", 0);
}

inline void System_CopyStringToClipboard(const std::string &string) {
g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, nullptr, nullptr, string, "", 0);
}
Expand Down
3 changes: 3 additions & 0 deletions Common/System/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ void System_LaunchUrl(LaunchUrlType urlType, const char *url);

enum class SystemRequestType {
INPUT_TEXT_MODAL,
ASK_USERNAME_PASSWORD,
BROWSE_FOR_IMAGE,
BROWSE_FOR_FILE,
BROWSE_FOR_FOLDER,
Expand Down Expand Up @@ -129,6 +130,8 @@ enum SystemProperty {
SYSPROP_HAS_BACK_BUTTON,
SYSPROP_HAS_KEYBOARD,
SYSPROP_HAS_OPEN_DIRECTORY,
SYSPROP_HAS_LOGIN_DIALOG,
SYSPROP_HAS_TEXT_INPUT_DIALOG, // Indicates that System_InputBoxGetString is available.

SYSPROP_CAN_CREATE_SHORTCUT,

Expand Down
20 changes: 19 additions & 1 deletion Common/UI/PopupScreens.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#include <algorithm>
#include <sstream>
#include <cstring>

#include "Common/UI/PopupScreens.h"
#include "Common/UI/ViewGroup.h"
#include "Common/UI/Context.h"
#include "Common/UI/Root.h"
#include "Common/StringUtils.h"
#include "Common/Data/Text/I18n.h"
#include "Common/System/System.h"
#include "Common/System/Request.h"

namespace UI {

Expand Down Expand Up @@ -495,6 +498,16 @@ PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string
EventReturn PopupTextInputChoice::HandleClick(EventParams &e) {
restoreFocus_ = HasFocus();

// Choose method depending on platform capabilities.
if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
System_InputBoxGetString(text_, *value_ , [=](const std::string &enteredValue, int) {
*value_ = StripSpaces(enteredValue);
EventParams params{};
OnChange.Trigger(params);
});
return EVENT_DONE;
}

TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, ChopTitle(text_), maxLen_);
popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange);
if (e.v)
Expand Down Expand Up @@ -582,7 +595,12 @@ void AbstractChoiceWithValueDisplay::Draw(UIContext &dc) {
int paddingX = 12;
dc.SetFontStyle(dc.theme->uiFont);

const std::string valueText = ValueText();
std::string valueText = ValueText();

if (password_) {
// Replace all characters with stars.
memset(&valueText[0], '*', valueText.size());
}

// If there is a label, assume we want at least 20% of the size for it, at a minimum.

Expand Down
7 changes: 7 additions & 0 deletions Common/UI/PopupScreens.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,16 @@ class AbstractChoiceWithValueDisplay : public UI::Choice {
void Draw(UIContext &dc) override;
void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override;

void SetPasswordDisplay() {
password_ = true;
}

protected:
virtual std::string ValueText() const = 0;

float CalculateValueScale(const UIContext &dc, const std::string &valueText, float availWidth) const;

bool password_ = false;
};

// Reads and writes value to determine the current selection.
Expand Down Expand Up @@ -359,6 +365,7 @@ class PopupSliderChoiceFloat : public AbstractChoiceWithValueDisplay {
bool hasDropShadow_ = true;
};

// NOTE: This one will defer to a system-native dialog if possible.
class PopupTextInputChoice : public AbstractChoiceWithValueDisplay {
public:
PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams = 0);
Expand Down
1 change: 1 addition & 0 deletions Qt/QtMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ bool System_GetPropertyBool(SystemProperty prop) {
case SYSPROP_HAS_FILE_BROWSER:
case SYSPROP_HAS_FOLDER_BROWSER:
case SYSPROP_HAS_OPEN_DIRECTORY:
case SYSPROP_HAS_TEXT_INPUT_DIALOG:
return true;
case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR:
return true; // FileUtil.cpp: OpenFileInEditor
Expand Down
4 changes: 4 additions & 0 deletions SDL/SDLMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,10 @@ bool System_GetPropertyBool(SystemProperty prop) {
#endif
case SYSPROP_HAS_BACK_BUTTON:
return true;
#if PPSSPP_PLATFORM(SWITCH)
case SYSPROP_HAS_TEXT_INPUT_DIALOG:
return true;
#endif
case SYSPROP_APP_GOLD:
#ifdef GOLD
return true;
Expand Down
17 changes: 2 additions & 15 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1053,17 +1053,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) {
systemSettings->Add(new ItemHeader(sy->T("PSP Settings")));
static const char *models[] = { "PSP-1000", "PSP-2000/3000" };
systemSettings->Add(new PopupMultiChoice(&g_Config.iPSPModel, sy->T("PSP Model"), models, 0, ARRAY_SIZE(models), I18NCat::SYSTEM, screenManager()))->SetEnabled(!PSP_IsInited());
// TODO: Come up with a way to display a keyboard for mobile users,
// so until then, this is Windows/Desktop only.
#if !defined(MOBILE_DEVICE) // TODO: Add all platforms where KEY_CHAR support is added
systemSettings->Add(new PopupTextInputChoice(&g_Config.sNickName, sy->T("Change Nickname"), "", 32, screenManager()));
#elif PPSSPP_PLATFORM(ANDROID)
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD))
systemSettings->Add(new ChoiceWithValueDisplay(&g_Config.sNickName, sy->T("Change Nickname"), I18NCat::NONE))->OnClick.Handle(this, &GameSettingsScreen::OnChangeNickname);
else
systemSettings->Add(new PopupTextInputChoice(&g_Config.sNickName, sy->T("Change Nickname"), "", 32, screenManager()));
#endif

systemSettings->Add(new CheckBox(&g_Config.bScreenshotsAsPNG, sy->T("Screenshots as PNG")));

#if defined(_WIN32) || (defined(USING_QT_UI) && !defined(MOBILE_DEVICE))
Expand Down Expand Up @@ -1879,10 +1869,9 @@ void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) {
buttonsRow1->Add(new Spacer(new LinearLayoutParams(1.0, G_RIGHT)));

buttonsRow2->Add(new Spacer(new LinearLayoutParams(1.0, G_LEFT)));
#if PPSSPP_PLATFORM(ANDROID)
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD))
if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
buttonsRow2->Add(new Button(di->T("Edit")))->OnClick.Handle(this, &HostnameSelectScreen::OnEditClick);
#endif
}
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 Button(di->T("Toggle List")))->OnClick.Handle(this, &HostnameSelectScreen::OnShowIPListClick);
Expand Down Expand Up @@ -1946,11 +1935,9 @@ UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) {

UI::EventReturn HostnameSelectScreen::OnEditClick(UI::EventParams& e) {
auto n = GetI18NCategory(I18NCat::NETWORKING);
#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH)
System_InputBoxGetString(n->T("proAdhocServer Address:"), addrView_->GetText(), [this](const std::string& value, int) {
addrView_->SetText(value);
});
#endif
return UI::EVENT_DONE;
}

Expand Down
4 changes: 1 addition & 3 deletions UI/MainScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1291,14 +1291,12 @@ bool MainScreen::key(const KeyInput &touch) {
if (touch.flags & KEY_DOWN) {
if (touch.keyCode == NKCODE_CTRL_LEFT || touch.keyCode == NKCODE_CTRL_RIGHT)
searchKeyModifier_ = true;
if (touch.keyCode == NKCODE_F && searchKeyModifier_) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) || PPSSPP_PLATFORM(SWITCH)
if (touch.keyCode == NKCODE_F && searchKeyModifier_ && System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
auto se = GetI18NCategory(I18NCat::SEARCH);
System_InputBoxGetString(se->T("Search term"), searchFilter_, [&](const std::string &value, int) {
searchFilter_ = StripSpaces(value);
searchChanged_ = true;
});
#endif
}
} else if (touch.flags & KEY_UP) {
if (touch.keyCode == NKCODE_CTRL_LEFT || touch.keyCode == NKCODE_CTRL_RIGHT)
Expand Down
34 changes: 0 additions & 34 deletions UI/RemoteISOScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -602,12 +602,6 @@ void RemoteISOSettingsScreen::CreateViews() {
remoteisoSettings->Add(new CheckBox(&g_Config.bRemoteISOManual, ri->T("Manual Mode Client", "Manually configure client")));

UI::Choice *remoteServer;
#if defined(MOBILE_DEVICE)
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
remoteServer = new ChoiceWithValueDisplay(&g_Config.sLastRemoteISOServer, ri->T("Remote Server"), I18NCat::NONE);
remoteServer->OnClick.Handle(this, &RemoteISOSettingsScreen::OnClickRemoteServer);
} else
#endif
remoteServer = new PopupTextInputChoice(&g_Config.sLastRemoteISOServer, ri->T("Remote Server"), "", 255, screenManager());
remoteisoSettings->Add(remoteServer);
remoteServer->SetEnabledPtr(&g_Config.bRemoteISOManual);
Expand All @@ -616,12 +610,6 @@ void RemoteISOSettingsScreen::CreateViews() {
remotePort->SetEnabledPtr(&g_Config.bRemoteISOManual);

UI::Choice *remoteSubdir;
#if defined(MOBILE_DEVICE)
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
remoteSubdir = new ChoiceWithValueDisplay(&g_Config.sRemoteISOSubdir, ri->T("Remote Subdirectory"), I18NCat::NONE);
remoteSubdir->OnClick.Handle(this, &RemoteISOSettingsScreen::OnClickRemoteISOSubdir);
} else
#endif
{
PopupTextInputChoice *remoteSubdirInput = new PopupTextInputChoice(&g_Config.sRemoteISOSubdir, ri->T("Remote Subdirectory"), "", 255, screenManager());
remoteSubdirInput->OnChange.Handle(this, &RemoteISOSettingsScreen::OnChangeRemoteISOSubdir);
Expand All @@ -640,16 +628,6 @@ void RemoteISOSettingsScreen::CreateViews() {
AddStandardBack(root_);
}

UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteServer(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) || PPSSPP_PLATFORM(SWITCH)
auto ri = GetI18NCategory(I18NCat::REMOTEISO);
System_InputBoxGetString(ri->T("Remote Server"), g_Config.sLastRemoteISOServer, [](const std::string &value, int) {
g_Config.sLastRemoteISOServer = value;
});
#endif
return UI::EVENT_DONE;
}

static void CleanupRemoteISOSubdir() {
// Replace spaces and force forward slashes.
// TODO: Maybe we should uri escape this after?
Expand All @@ -660,18 +638,6 @@ static void CleanupRemoteISOSubdir() {
g_Config.sRemoteISOSubdir = "/" + g_Config.sRemoteISOSubdir;
}

UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteISOSubdir(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) || PPSSPP_PLATFORM(SWITCH)
auto ri = GetI18NCategory(I18NCat::REMOTEISO);
System_InputBoxGetString(ri->T("Remote Subdirectory"), g_Config.sRemoteISOSubdir, [](const std::string &value, int) {
g_Config.sRemoteISOSubdir = value;
// Apply the cleanup logic, too.
CleanupRemoteISOSubdir();
});
#endif
return UI::EVENT_DONE;
}

UI::EventReturn RemoteISOSettingsScreen::OnChangeRemoteISOSubdir(UI::EventParams &e) {
CleanupRemoteISOSubdir();
return UI::EVENT_DONE;
Expand Down
3 changes: 0 additions & 3 deletions UI/RemoteISOScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,7 @@ class RemoteISOSettingsScreen : public UIDialogScreenWithBackground {

const char *tag() const override { return "RemoteISOSettings"; }

UI::EventReturn OnClickRemoteISOSubdir(UI::EventParams &e);
UI::EventReturn OnClickRemoteServer(UI::EventParams &e);
protected:

void update() override;
void CreateViews() override;

Expand Down
17 changes: 9 additions & 8 deletions UI/SavedataScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,9 @@ void SavedataScreen::CreateViews() {
sortStrip->OnChoice.Handle<SavedataScreen>(this, &SavedataScreen::OnSortClick);

AddStandardBack(root_);
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD))
if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
root_->Add(new Choice(di->T("Search"), "", false, new AnchorLayoutParams(WRAP_CONTENT, 64, NONE, NONE, 10, 10)))->OnClick.Handle<SavedataScreen>(this, &SavedataScreen::OnSearch);
}

root_->Add(main);
root_->Add(sortStrip);
Expand All @@ -672,13 +673,13 @@ UI::EventReturn SavedataScreen::OnSortClick(UI::EventParams &e) {

UI::EventReturn SavedataScreen::OnSearch(UI::EventParams &e) {
auto di = GetI18NCategory(I18NCat::DIALOG);
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) || PPSSPP_PLATFORM(SWITCH)
System_InputBoxGetString(di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) {
if (ivalue) {
NativeMessageReceived("savedatascreen_search", value.c_str());
}
});
#endif
if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
System_InputBoxGetString(di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) {
if (ivalue) {
NativeMessageReceived("savedatascreen_search", value.c_str());
}
});
}
return UI::EVENT_DONE;
}

Expand Down
60 changes: 23 additions & 37 deletions UI/TabbedDialogScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,27 +78,31 @@ void TabbedUIDialogScreenWithGameBackground::CreateViews() {
// Let the subclass create its tabs.
CreateTabs();

#if !defined(MOBILE_DEVICE) || PPSSPP_PLATFORM(ANDROID)
// Hide search if screen is too small.
int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE);
if ((g_display.dp_xres < g_display.dp_yres || g_display.dp_yres >= 500) && (deviceType != DEVICE_TYPE_VR) && ShowSearchControls()) {
auto se = GetI18NCategory(I18NCat::SEARCH);
// Search
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);

searchSettings->Add(new ItemHeader(se->T("Find settings")));
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
searchSettings->Add(new ChoiceWithValueDisplay(&searchFilter_, se->T("Filter"), I18NCat::NONE))->OnClick.Handle(this, &TabbedUIDialogScreenWithGameBackground::OnChangeSearchFilter);
} else {
searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Handle(this, &TabbedUIDialogScreenWithGameBackground::OnChangeSearchFilter);
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD) || System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
// Hide search if screen is too small.
int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE);
if ((g_display.dp_xres < g_display.dp_yres || g_display.dp_yres >= 500) && (deviceType != DEVICE_TYPE_VR) && ShowSearchControls()) {
auto se = GetI18NCategory(I18NCat::SEARCH);
// Search
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);

searchSettings->Add(new ItemHeader(se->T("Find settings")));
searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Add([=](UI::EventParams &e) {
NativeMessageReceived("gameSettings_search", StripSpaces(searchFilter_).c_str());
return UI::EVENT_DONE;
});

clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
clearSearchChoice_->OnClick.Add([=](UI::EventParams &e) {
NativeMessageReceived("gameSettings_search", "");
return UI::EVENT_DONE;
});

noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));

ApplySearchFilter();
}
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
clearSearchChoice_->OnClick.Handle(this, &TabbedUIDialogScreenWithGameBackground::OnClearSearchFilter);
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));

ApplySearchFilter();
}
#endif
}

void TabbedUIDialogScreenWithGameBackground::sendMessage(const char *message, const char *value) {
Expand Down Expand Up @@ -153,21 +157,3 @@ void TabbedUIDialogScreenWithGameBackground::ApplySearchFilter() {
noSearchResults_->SetVisibility(matches ? UI::V_GONE : UI::V_VISIBLE);
clearSearchChoice_->SetVisibility(searchFilter_.empty() ? UI::V_GONE : UI::V_VISIBLE);
}

UI::EventReturn TabbedUIDialogScreenWithGameBackground::OnChangeSearchFilter(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) || PPSSPP_PLATFORM(SWITCH)
auto se = GetI18NCategory(I18NCat::SEARCH);
System_InputBoxGetString(se->T("Search term"), searchFilter_, [](const std::string &value, int) {
NativeMessageReceived("gameSettings_search", StripSpaces(value).c_str());
});
#else
if (!System_GetPropertyBool(SYSPROP_HAS_KEYBOARD))
NativeMessageReceived("gameSettings_search", StripSpaces(searchFilter_).c_str());
#endif
return UI::EVENT_DONE;
}

UI::EventReturn TabbedUIDialogScreenWithGameBackground::OnClearSearchFilter(UI::EventParams &e) {
NativeMessageReceived("gameSettings_search", "");
return UI::EVENT_DONE;
}
2 changes: 0 additions & 2 deletions UI/TabbedDialogScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ class TabbedUIDialogScreenWithGameBackground : public UIDialogScreenWithGameBack

void RecreateViews() override;

UI::EventReturn OnChangeSearchFilter(UI::EventParams &e);
UI::EventReturn OnClearSearchFilter(UI::EventParams &e);
SettingInfoMessage *settingInfo_ = nullptr;

private:
Expand Down
Loading

0 comments on commit a56f74c

Please sign in to comment.