mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Move more of the search code out of GameBrowser
This commit is contained in:
@@ -558,122 +558,12 @@ bool GameBrowser::Key(const KeyInput &input) {
|
||||
return search_.Key(gameList_, input);
|
||||
}
|
||||
|
||||
bool SearchEngine::Key(UI::ViewGroup *viewGroup, const KeyInput &input) {
|
||||
bool retval = false;
|
||||
// Only one is visible at a time, so we can just grab all Char input.
|
||||
if (input.flags & KeyInputFlags::CHAR) {
|
||||
const int unichar = input.keyCode;
|
||||
if (unichar >= 0x20) {
|
||||
// TODO: Save focus state here.
|
||||
|
||||
// Insert it! (todo: do it with a string insert)
|
||||
char buf[8];
|
||||
buf[u8_wc_toutf8(buf, unichar)] = '\0';
|
||||
searchFilter += buf;
|
||||
ApplySearchFilter(viewGroup, true);
|
||||
retval = true;
|
||||
}
|
||||
} else if (input.flags & KeyInputFlags::DOWN) {
|
||||
if (input.keyCode == NKCODE_DEL) {
|
||||
if (!searchFilter.empty()) {
|
||||
searchFilter.pop_back();
|
||||
ApplySearchFilter(viewGroup, true);
|
||||
retval = true;
|
||||
if (searchFilter.empty()) {
|
||||
// TODO: Restore focus state here.
|
||||
UI::EnableFocusMovement(false);
|
||||
}
|
||||
} else {
|
||||
// Empty search filter. Navigate upwards on backspace?
|
||||
}
|
||||
} else if (!searchFilter.empty() && input.keyCode == NKCODE_ESCAPE) {
|
||||
searchFilter.clear();
|
||||
ApplySearchFilter(viewGroup, false);
|
||||
retval = true;
|
||||
|
||||
// TODO: Restore focus state here.
|
||||
UI::EnableFocusMovement(false);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void GameBrowser::SetSearchFilter(const std::string &filter, bool setKeyboardFocus) {
|
||||
search_.searchFilter = filter;
|
||||
// We don't refresh because game info loads asynchronously anyway.
|
||||
search_.ApplySearchFilter(gameList_, setKeyboardFocus);
|
||||
}
|
||||
|
||||
void SearchEngine::ApplySearchFilter(UI::ViewGroup *viewGroup, bool setKeyboardFocus) {
|
||||
if (searchBar) {
|
||||
searchBar->SetSearchFilter(searchFilter);
|
||||
searchBar->SetVisibility(searchFilter.empty() ? UI::V_GONE : UI::V_VISIBLE);
|
||||
}
|
||||
|
||||
if (searchFilter.empty() && searchStates.empty()) {
|
||||
// We haven't hidden anything, and we're not searching, so do nothing.
|
||||
searchPending = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filter = NormalizeForSearch(searchFilter);
|
||||
|
||||
searchPending = false;
|
||||
// By default, everything is matching.
|
||||
searchStates.resize(viewGroup->GetNumSubviews(), SearchState::MATCH);
|
||||
if (filter.empty()) {
|
||||
// Just quickly mark anything we hid as visible again.
|
||||
for (int i = 0; i < viewGroup->GetNumSubviews(); ++i) {
|
||||
UI::View *v = viewGroup->GetViewByIndex(i);
|
||||
if (searchStates[i] != SearchState::MATCH)
|
||||
v->SetVisibility(UI::V_VISIBLE);
|
||||
}
|
||||
|
||||
searchStates.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
UI::View *firstMatch = nullptr;
|
||||
|
||||
for (int i = 0; i < viewGroup->GetNumSubviews(); ++i) {
|
||||
UI::View *v = viewGroup->GetViewByIndex(i);
|
||||
std::string label = v->DescribeText();
|
||||
// This is a bit of a hack to recognize a pending game title.
|
||||
if (label == "...") {
|
||||
searchPending = true;
|
||||
// Hide anything pending while, we'll pop-in search results as they match.
|
||||
// Note: we leave it at MATCH if gone before, so we don't show it again.
|
||||
if (v->GetVisibility() == UI::V_VISIBLE) {
|
||||
if (searchStates[i] == SearchState::MATCH)
|
||||
v->SetVisibility(UI::V_GONE);
|
||||
searchStates[i] = SearchState::PENDING;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
label = NormalizeForSearch(label);
|
||||
bool match = v->CanBeFocused() && label.find(filter) != label.npos;
|
||||
if (match && !firstMatch) {
|
||||
firstMatch = v;
|
||||
}
|
||||
if (match && searchStates[i] != SearchState::MATCH) {
|
||||
// It was previously visible and force hidden, so show it again.
|
||||
v->SetVisibility(UI::V_VISIBLE);
|
||||
searchStates[i] = SearchState::MATCH;
|
||||
} else if (!match && searchStates[i] == SearchState::MATCH && v->GetVisibility() == UI::V_VISIBLE) {
|
||||
v->SetVisibility(UI::V_GONE);
|
||||
searchStates[i] = SearchState::MISMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstMatch) {
|
||||
if (setKeyboardFocus) {
|
||||
UI::EnableFocusMovement(true);
|
||||
}
|
||||
UI::SetFocusedView(firstMatch);
|
||||
}
|
||||
}
|
||||
|
||||
void GameBrowser::LayoutChange(UI::EventParams &e) {
|
||||
*gridStyle_ = e.a == 0 ? true : false;
|
||||
Refresh();
|
||||
|
||||
+1
-17
@@ -24,22 +24,6 @@ enum class BrowseFlags {
|
||||
};
|
||||
ENUM_CLASS_BITOPS(BrowseFlags);
|
||||
|
||||
enum class SearchState {
|
||||
MATCH,
|
||||
MISMATCH,
|
||||
PENDING,
|
||||
};
|
||||
|
||||
struct SearchEngine {
|
||||
SearchBar *searchBar;
|
||||
std::string searchFilter;
|
||||
std::vector<SearchState> searchStates;
|
||||
bool searchPending;
|
||||
|
||||
void ApplySearchFilter(UI::ViewGroup *viewGroup, bool setKeyboardFocus);
|
||||
bool Key(UI::ViewGroup *viewGroup, const KeyInput &input);
|
||||
};
|
||||
|
||||
class GameBrowser : public UI::LinearLayout {
|
||||
public:
|
||||
GameBrowser(int token, const Path &path, BrowseFlags browseFlags, bool portrait, bool *gridStyle, ScreenManager *screenManager, std::string_view lastText, std::string_view lastLink, UI::LayoutParams *layoutParams = nullptr);
|
||||
@@ -97,7 +81,7 @@ private:
|
||||
std::string lastText_;
|
||||
std::string lastLink_;
|
||||
|
||||
SearchEngine search_{};
|
||||
ViewSearch search_{};
|
||||
|
||||
Path focusGamePath_;
|
||||
bool listingPending_ = false;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Math/curves.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include "Common/UI/Root.h"
|
||||
#include "UI/MiscViews.h"
|
||||
#include "UI/GameInfoCache.h"
|
||||
#include "Common/UI/PopupScreens.h"
|
||||
@@ -350,3 +352,113 @@ bool SearchBar::Touch(const TouchInput &input) {
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void ViewSearch::ApplySearchFilter(UI::ViewGroup *viewGroup, bool setKeyboardFocus) {
|
||||
if (searchBar) {
|
||||
searchBar->SetSearchFilter(searchFilter);
|
||||
searchBar->SetVisibility(searchFilter.empty() ? UI::V_GONE : UI::V_VISIBLE);
|
||||
}
|
||||
|
||||
if (searchFilter.empty() && searchStates.empty()) {
|
||||
// We haven't hidden anything, and we're not searching, so do nothing.
|
||||
searchPending = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filter = NormalizeForSearch(searchFilter);
|
||||
|
||||
searchPending = false;
|
||||
// By default, everything is matching.
|
||||
searchStates.resize(viewGroup->GetNumSubviews(), SearchState::MATCH);
|
||||
if (filter.empty()) {
|
||||
// Just quickly mark anything we hid as visible again.
|
||||
for (int i = 0; i < viewGroup->GetNumSubviews(); ++i) {
|
||||
UI::View *v = viewGroup->GetViewByIndex(i);
|
||||
if (searchStates[i] != SearchState::MATCH)
|
||||
v->SetVisibility(UI::V_VISIBLE);
|
||||
}
|
||||
|
||||
searchStates.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
UI::View *firstMatch = nullptr;
|
||||
|
||||
for (int i = 0; i < viewGroup->GetNumSubviews(); ++i) {
|
||||
UI::View *v = viewGroup->GetViewByIndex(i);
|
||||
std::string label = v->DescribeText();
|
||||
// This is a bit of a hack to recognize a pending game title.
|
||||
if (label == "...") {
|
||||
searchPending = true;
|
||||
// Hide anything pending while, we'll pop-in search results as they match.
|
||||
// Note: we leave it at MATCH if gone before, so we don't show it again.
|
||||
if (v->GetVisibility() == UI::V_VISIBLE) {
|
||||
if (searchStates[i] == SearchState::MATCH)
|
||||
v->SetVisibility(UI::V_GONE);
|
||||
searchStates[i] = SearchState::PENDING;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
label = NormalizeForSearch(label);
|
||||
bool match = v->CanBeFocused() && label.find(filter) != label.npos;
|
||||
if (match && !firstMatch) {
|
||||
firstMatch = v;
|
||||
}
|
||||
if (match && searchStates[i] != SearchState::MATCH) {
|
||||
// It was previously visible and force hidden, so show it again.
|
||||
v->SetVisibility(UI::V_VISIBLE);
|
||||
searchStates[i] = SearchState::MATCH;
|
||||
} else if (!match && searchStates[i] == SearchState::MATCH && v->GetVisibility() == UI::V_VISIBLE) {
|
||||
v->SetVisibility(UI::V_GONE);
|
||||
searchStates[i] = SearchState::MISMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstMatch) {
|
||||
if (setKeyboardFocus) {
|
||||
UI::EnableFocusMovement(true);
|
||||
}
|
||||
UI::SetFocusedView(firstMatch);
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewSearch::Key(UI::ViewGroup *viewGroup, const KeyInput &input) {
|
||||
bool retval = false;
|
||||
// Only one is visible at a time, so we can just grab all Char input.
|
||||
if (input.flags & KeyInputFlags::CHAR) {
|
||||
const int unichar = input.keyCode;
|
||||
if (unichar >= 0x20) {
|
||||
// TODO: Save focus state here.
|
||||
|
||||
// Insert it! (todo: do it with a string insert)
|
||||
char buf[8];
|
||||
buf[u8_wc_toutf8(buf, unichar)] = '\0';
|
||||
searchFilter += buf;
|
||||
ApplySearchFilter(viewGroup, true);
|
||||
retval = true;
|
||||
}
|
||||
} else if (input.flags & KeyInputFlags::DOWN) {
|
||||
if (input.keyCode == NKCODE_DEL) {
|
||||
if (!searchFilter.empty()) {
|
||||
searchFilter.pop_back();
|
||||
ApplySearchFilter(viewGroup, true);
|
||||
retval = true;
|
||||
if (searchFilter.empty()) {
|
||||
// TODO: Restore focus state here.
|
||||
UI::EnableFocusMovement(false);
|
||||
}
|
||||
} else {
|
||||
// Empty search filter. Navigate upwards on backspace?
|
||||
}
|
||||
} else if (!searchFilter.empty() && input.keyCode == NKCODE_ESCAPE) {
|
||||
searchFilter.clear();
|
||||
ApplySearchFilter(viewGroup, false);
|
||||
retval = true;
|
||||
|
||||
// TODO: Restore focus state here.
|
||||
UI::EnableFocusMovement(false);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -115,3 +115,19 @@ public:
|
||||
private:
|
||||
std::string searchFilter_ = "N/A";
|
||||
};
|
||||
|
||||
enum class SearchState {
|
||||
MATCH,
|
||||
MISMATCH,
|
||||
PENDING,
|
||||
};
|
||||
|
||||
struct ViewSearch {
|
||||
SearchBar *searchBar;
|
||||
std::string searchFilter;
|
||||
std::vector<SearchState> searchStates;
|
||||
bool searchPending;
|
||||
|
||||
void ApplySearchFilter(UI::ViewGroup *viewGroup, bool setKeyboardFocus);
|
||||
bool Key(UI::ViewGroup *viewGroup, const KeyInput &input);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user