Skip to content

Commit

Permalink
Merge pull request #14237 from unknownbrackets/ui-search
Browse files Browse the repository at this point in the history
Add initial search to savedata manager
  • Loading branch information
hrydgard authored Mar 8, 2021
2 parents 1cfaa9f + b050a07 commit 977b48f
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 36 deletions.
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

0 comments on commit 977b48f

Please sign in to comment.