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

Add initial search to savedata manager #14237

Merged
merged 2 commits into from
Mar 8, 2021
Merged
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
12 changes: 6 additions & 6 deletions Common/UI/ViewGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1288,7 +1288,7 @@ void TabHolder::SetCurrentTab(int tab, bool skipTween) {

currentTab_ = tab;
}
tabStrip_->SetSelection(tab);
tabStrip_->SetSelection(tab, false);
}

EventReturn TabHolder::OnTabClick(EventParams &e) {
Expand Down Expand Up @@ -1369,7 +1369,7 @@ EventReturn ChoiceStrip::OnChoiceClick(EventParams &e) {
return OnChoice.Dispatch(e2);
}

void ChoiceStrip::SetSelection(int sel) {
void ChoiceStrip::SetSelection(int sel, bool triggerClick) {
int prevSelected = selected_;
StickyChoice *prevChoice = Choice(selected_);
if (prevChoice)
Expand All @@ -1384,7 +1384,7 @@ void ChoiceStrip::SetSelection(int sel) {
e.v = views_[selected_];
e.a = selected_;
// Set to 0 to indicate a selection change (not a click.)
e.b = 0;
e.b = triggerClick ? 1 : 0;
OnChoice.Trigger(e);
}
}
Expand All @@ -1398,16 +1398,16 @@ void ChoiceStrip::HighlightChoice(unsigned int choice){

bool ChoiceStrip::Key(const KeyInput &input) {
bool ret = false;
if (input.flags & KEY_DOWN) {
if (topTabs_ && (input.flags & KEY_DOWN)) {
if (IsTabLeftKey(input)) {
if (selected_ > 0) {
SetSelection(selected_ - 1);
SetSelection(selected_ - 1, true);
UI::PlayUISound(UI::UISound::TOGGLE_OFF); // Maybe make specific sounds for this at some point?
}
ret = true;
} else if (IsTabRightKey(input)) {
if (selected_ < (int)views_.size() - 1) {
SetSelection(selected_ + 1);
SetSelection(selected_ + 1, true);
UI::PlayUISound(UI::UISound::TOGGLE_ON);
}
ret = true;
Expand Down
2 changes: 1 addition & 1 deletion Common/UI/ViewGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ class ChoiceStrip : public LinearLayout {
void AddChoice(ImageID buttonImage);

int GetSelection() const { return selected_; }
void SetSelection(int sel);
void SetSelection(int sel, bool triggerClick);

void HighlightChoice(unsigned int choice);

Expand Down
2 changes: 1 addition & 1 deletion UI/ComboKeyMappingScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void ComboKeyScreen::CreateViews() {
for (int i = 0; i < 5; i++) {
comboselect->AddChoice(comboKeyImages[i]);
}
comboselect->SetSelection(*mode);
comboselect->SetSelection(*mode, false);
comboselect->OnChoice.Handle(this, &ComboKeyScreen::onCombo);
leftColumn->Add(comboselect);
root__->Add(leftColumn);
Expand Down
2 changes: 1 addition & 1 deletion UI/DisplayLayoutScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ void DisplayLayoutScreen::CreateViews() {
mode_ = new ChoiceStrip(ORIENT_VERTICAL, new AnchorLayoutParams(leftColumnWidth, WRAP_CONTENT, 10 + leftInset, NONE, NONE, 158 + 64 + 10));
mode_->AddChoice(di->T("Move"));
mode_->AddChoice(di->T("Resize"));
mode_->SetSelection(0);
mode_->SetSelection(0, false);
}
displayRepresentation_ = new DragDropDisplay(g_Config.fSmallDisplayOffsetX, g_Config.fSmallDisplayOffsetY, ImageID("I_PSP_DISPLAY"), ScaleSettingToUI(), bounds);
displayRepresentation_->SetVisibility(V_VISIBLE);
Expand Down
2 changes: 1 addition & 1 deletion UI/MainScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ void GameBrowser::Refresh() {
ChoiceStrip *layoutChoice = topBar->Add(new ChoiceStrip(ORIENT_HORIZONTAL));
layoutChoice->AddChoice(ImageID("I_GRID"));
layoutChoice->AddChoice(ImageID("I_LINES"));
layoutChoice->SetSelection(*gridStyle_ ? 0 : 1);
layoutChoice->SetSelection(*gridStyle_ ? 0 : 1, false);
layoutChoice->OnChoice.Handle(this, &GameBrowser::LayoutChange);
topBar->Add(new Choice(ImageID("I_GEAR"), new LayoutParams(64.0f, 64.0f)))->OnClick.Handle(this, &GameBrowser::GridSettingsClick);
Add(topBar);
Expand Down
159 changes: 134 additions & 25 deletions UI/SavedataScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@

#include "Common/Data/Color/RGBAUtil.h"
#include "Common/Render/DrawBuffer.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/Data/Text/I18n.h"
#include "Common/Math/curves.h"
#include "Common/System/NativeApp.h"
#include "Common/System/System.h"
#include "Common/Thread/PrioritizedWorkQueue.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/UI/Context.h"
#include "Common/UI/View.h"
#include "Common/UI/ViewGroup.h"
Expand Down Expand Up @@ -174,6 +176,7 @@ class SavedataButton : public UI::Clickable {
}

void Draw(UIContext &dc) override;
bool UpdateText();
std::string DescribeText() const override;
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override {
w = 500;
Expand All @@ -183,6 +186,8 @@ class SavedataButton : public UI::Clickable {
const std::string &GamePath() const { return savePath_; }

private:
void UpdateText(const std::shared_ptr<GameInfo> &ginfo);

std::string savePath_;
std::string title_;
std::string subtitle_;
Expand All @@ -202,6 +207,26 @@ static std::string CleanSaveString(std::string str) {
return s;
}

bool SavedataButton::UpdateText() {
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GAMEINFO_WANTSIZE);
if (!ginfo->pending) {
UpdateText(ginfo);
return true;
}
return false;
}

void SavedataButton::UpdateText(const std::shared_ptr<GameInfo> &ginfo) {
const std::string currentTitle = ginfo->GetTitle();
if (!currentTitle.empty()) {
title_ = CleanSaveString(currentTitle);
}
if (subtitle_.empty() && ginfo->gameSize > 0) {
std::string savedata_title = ginfo->paramSFO.GetValueString("SAVEDATA_TITLE");
subtitle_ = CleanSaveString(savedata_title) + StringFromFormat(" (%lld kB)", ginfo->gameSize / 1024);
}
}

void SavedataButton::Draw(UIContext &dc) {
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), savePath_, GAMEINFO_WANTSIZE);
Draw::Texture *texture = 0;
Expand Down Expand Up @@ -287,15 +312,7 @@ void SavedataButton::Draw(UIContext &dc) {
dc.Draw()->Flush();
dc.PushScissor(bounds_);

const std::string currentTitle = ginfo->GetTitle();
if (!currentTitle.empty()) {
title_ = CleanSaveString(currentTitle);
}
if (subtitle_.empty() && ginfo->gameSize > 0) {
std::string savedata_title = ginfo->paramSFO.GetValueString("SAVEDATA_TITLE");
subtitle_ = CleanSaveString(savedata_title) + StringFromFormat(" (%lld kB)", ginfo->gameSize / 1024);
}

UpdateText(ginfo);
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, title_.c_str(), &tw, &th, 0);

int availableWidth = bounds_.w - 150;
Expand Down Expand Up @@ -334,6 +351,58 @@ SavedataBrowser::SavedataBrowser(std::string path, UI::LayoutParams *layoutParam
Refresh();
}

void SavedataBrowser::Update() {
if (searchPending_) {
searchPending_ = false;

int n = gameList_->GetNumSubviews();
bool matches = searchFilter_.empty();
for (int i = 0; i < n; ++i) {
SavedataButton *v = static_cast<SavedataButton *>(gameList_->GetViewByIndex(i));

// Note: might be resetting to empty string. Can do that right away.
if (searchFilter_.empty()) {
v->SetVisibility(UI::V_VISIBLE);
continue;
}

if (!v->UpdateText()) {
// We'll need to wait until the text is loaded.
searchPending_ = true;
v->SetVisibility(UI::V_GONE);
continue;
}

std::string label = v->DescribeText();
std::transform(label.begin(), label.end(), label.begin(), tolower);
bool match = label.find(searchFilter_) != label.npos;
matches = matches || match;
v->SetVisibility(match ? UI::V_VISIBLE : UI::V_GONE);
}

if (searchingView_) {
bool show = !searchFilter_.empty() && (matches || searchPending_);
searchingView_->SetVisibility(show ? UI::V_VISIBLE : UI::V_GONE);
}
if (noMatchView_)
noMatchView_->SetVisibility(matches || searchPending_ ? UI::V_GONE : UI::V_VISIBLE);
}
}

void SavedataBrowser::SetSearchFilter(const std::string &filter) {
auto sa = GetI18NCategory("Savedata");

searchFilter_.resize(filter.size());
std::transform(filter.begin(), filter.end(), searchFilter_.begin(), tolower);

if (gameList_)
searchPending_ = true;
if (noMatchView_)
noMatchView_->SetText(ReplaceAll(sa->T("Nothing matching '%1' was found."), "%1", filter));
if (searchingView_)
searchingView_->SetText(ReplaceAll(sa->T("Showing matches for '%1'."), "%1", filter));
}

void SavedataBrowser::SetSortOption(SavedataSortOption opt) {
sortOption_ = opt;
if (gameList_) {
Expand Down Expand Up @@ -415,16 +484,10 @@ void SavedataBrowser::Refresh() {
auto mm = GetI18NCategory("MainMenu");
auto sa = GetI18NCategory("Savedata");

SortedLinearLayout *gl = new SortedLinearLayout(UI::ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
gl->SetSpacing(4.0f);
gameList_ = gl;
Add(gameList_);

// Find games in the current directory and create new ones.
std::vector<SavedataButton *> savedataButtons;

std::vector<FileInfo> fileInfo;

getFilesInDir(path_.c_str(), &fileInfo, "ppst:");

for (size_t i = 0; i < fileInfo.size(); i++) {
Expand All @@ -439,19 +502,35 @@ void SavedataBrowser::Refresh() {
}
}

for (size_t i = 0; i < savedataButtons.size(); i++) {
SavedataButton *b = gameList_->Add(savedataButtons[i]);
b->OnClick.Handle(this, &SavedataBrowser::SavedataButtonClick);
}
ViewGroup *group = new LinearLayout(ORIENT_VERTICAL, new UI::LinearLayoutParams(UI::Margins(12, 0)));
Add(group);

if (savedataButtons.empty()) {
ViewGroup *group = new LinearLayout(ORIENT_VERTICAL, new UI::LinearLayoutParams(UI::Margins(12, 0)));
group->Add(new TextView(sa->T("None yet. Things will appear here after you save.")));
gameList_->Add(group);
gameList_ = nullptr;
noMatchView_ = nullptr;
searchingView_ = nullptr;
} else {
noMatchView_ = group->Add(new TextView(sa->T("Nothing matching '%1' was found")));
noMatchView_->SetVisibility(UI::V_GONE);
searchingView_ = group->Add(new TextView(sa->T("Showing matches for '%1'")));
searchingView_->SetVisibility(UI::V_GONE);

SortedLinearLayout *gl = new SortedLinearLayout(UI::ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
gl->SetSpacing(4.0f);
gameList_ = gl;
Add(gameList_);

for (size_t i = 0; i < savedataButtons.size(); i++) {
SavedataButton *b = gameList_->Add(savedataButtons[i]);
b->OnClick.Handle(this, &SavedataBrowser::SavedataButtonClick);
}
}

// Reapply.
SetSortOption(sortOption_);
if (!searchFilter_.empty())
SetSearchFilter(searchFilter_);
}

UI::EventReturn SavedataBrowser::SavedataButtonClick(UI::EventParams &e) {
Expand Down Expand Up @@ -484,14 +563,17 @@ void SavedataScreen::CreateViews() {
gridStyle_ = false;
root_ = new AnchorLayout();

LinearLayout *main = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT));
// Make space for buttons.
LinearLayout *main = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, 0, 0, 0, 84.0f));

TabHolder *tabs = new TabHolder(ORIENT_HORIZONTAL, 64, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f));
tabs->SetTag("Savedata");
ScrollView *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
scroll->SetTag("SavedataBrowser");
dataBrowser_ = scroll->Add(new SavedataBrowser(savedata_dir, new LayoutParams(FILL_PARENT, FILL_PARENT)));
dataBrowser_->SetSortOption(sortOption_);
if (!searchFilter_.empty())
dataBrowser_->SetSearchFilter(searchFilter_);
dataBrowser_->OnChoice.Handle(this, &SavedataScreen::OnSavedataButtonClick);

tabs->AddTab(sa->T("Save Data"), scroll);
Expand All @@ -500,19 +582,25 @@ void SavedataScreen::CreateViews() {
scroll2->SetTag("SavedataStatesBrowser");
stateBrowser_ = scroll2->Add(new SavedataBrowser(savestate_dir));
stateBrowser_->SetSortOption(sortOption_);
if (!searchFilter_.empty())
stateBrowser_->SetSearchFilter(searchFilter_);
stateBrowser_->OnChoice.Handle(this, &SavedataScreen::OnSavedataButtonClick);
tabs->AddTab(sa->T("Save States"), scroll2);

main->Add(tabs);
main->Add(new Button(di->T("Back"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);

ChoiceStrip *sortStrip = new ChoiceStrip(ORIENT_HORIZONTAL, new AnchorLayoutParams(NONE, 0, 0, NONE));
sortStrip->AddChoice(sa->T("Filename"));
sortStrip->AddChoice(sa->T("Size"));
sortStrip->AddChoice(sa->T("Date"));
sortStrip->SetSelection((int)sortOption_);
sortStrip->SetSelection((int)sortOption_, false);
sortStrip->OnChoice.Handle<SavedataScreen>(this, &SavedataScreen::OnSortClick);

AddStandardBack(root_);
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__)
root_->Add(new Choice(di->T("Search"), "", false, new AnchorLayoutParams(WRAP_CONTENT, 64, NONE, NONE, 10, 10)))->OnClick.Handle<SavedataScreen>(this, &SavedataScreen::OnSearch);
#endif

root_->Add(main);
root_->Add(sortStrip);
}
Expand All @@ -526,6 +614,18 @@ UI::EventReturn SavedataScreen::OnSortClick(UI::EventParams &e) {
return UI::EVENT_DONE;
}

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

UI::EventReturn SavedataScreen::OnSavedataButtonClick(UI::EventParams &e) {
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), e.s, 0);
SavedataPopupScreen *popupScreen = new SavedataPopupScreen(e.s, ginfo->GetTitle());
Expand All @@ -542,3 +642,12 @@ void SavedataScreen::dialogFinished(const Screen *dialog, DialogResult result) {
RecreateViews();
}
}

void SavedataScreen::sendMessage(const char *message, const char *value) {
UIDialogScreenWithGameBackground::sendMessage(message, value);
if (!strcmp(message, "savedatascreen_search")) {
searchFilter_ = value;
dataBrowser_->SetSearchFilter(searchFilter_);
stateBrowser_->SetSearchFilter(searchFilter_);
}
}
11 changes: 11 additions & 0 deletions UI/SavedataScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ class SavedataBrowser : public UI::LinearLayout {
public:
SavedataBrowser(std::string path, UI::LayoutParams *layoutParams = 0);

void Update() override;

void SetSortOption(SavedataSortOption opt);
void SetSearchFilter(const std::string &filter);

UI::Event OnChoice;

Expand All @@ -51,7 +54,11 @@ class SavedataBrowser : public UI::LinearLayout {

SavedataSortOption sortOption_ = SavedataSortOption::FILENAME;
UI::ViewGroup *gameList_ = nullptr;
UI::TextView *noMatchView_ = nullptr;
UI::TextView *searchingView_ = nullptr;
std::string path_;
std::string searchFilter_;
bool searchPending_ = false;
};

class SavedataScreen : public UIDialogScreenWithGameBackground {
Expand All @@ -61,13 +68,17 @@ class SavedataScreen : public UIDialogScreenWithGameBackground {
~SavedataScreen();

void dialogFinished(const Screen *dialog, DialogResult result) override;
void sendMessage(const char *message, const char *value) override;

protected:
UI::EventReturn OnSavedataButtonClick(UI::EventParams &e);
UI::EventReturn OnSortClick(UI::EventParams &e);
UI::EventReturn OnSearch(UI::EventParams &e);
void CreateViews() override;

bool gridStyle_;
SavedataSortOption sortOption_ = SavedataSortOption::FILENAME;
SavedataBrowser *dataBrowser_;
SavedataBrowser *stateBrowser_;
std::string searchFilter_;
};
Loading