From c5934477b1ddd95b0814b3823f79a41cd7877d61 Mon Sep 17 00:00:00 2001
From: Periokumene <116148983+Periokumene@users.noreply.github.com>
Date: Fri, 19 Jul 2024 12:20:26 +0800
Subject: [PATCH 1/2] UE4 Compability by magical template

---
 SlateIconBrowser.uplugin                      |  1 -
 .../Private/SlateIconBrowser.cpp              | 88 +++++++++++++++----
 .../Private/SlateIconBrowserHacker.cpp        | 64 ++++++++++++++
 .../Private/SlateIconBrowserStyle.cpp         | 13 ++-
 .../Public/SlateIconBrowser.h                 |  8 ++
 .../Public/SlateIconBrowserHacker.h           | 53 +++++++++++
 .../Public/SlateIconBrowserUserSettings.h     |  4 +-
 .../SlateIconBrowser.Build.cs                 |  4 +
 8 files changed, 215 insertions(+), 20 deletions(-)
 create mode 100644 Source/SlateIconBrowser/Private/SlateIconBrowserHacker.cpp
 create mode 100644 Source/SlateIconBrowser/Public/SlateIconBrowserHacker.h

diff --git a/SlateIconBrowser.uplugin b/SlateIconBrowser.uplugin
index 16143ea..ce39c28 100644
--- a/SlateIconBrowser.uplugin
+++ b/SlateIconBrowser.uplugin
@@ -9,7 +9,6 @@
   "CreatedByURL": "https://sirjofri.de",
   "DocsURL": "https://github.com/sirjofri/SlateIconBrowser/blob/master/Readme.md",
   "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/7f51deb58ead4fed88abc798ca7c9ae4",
-  "EngineVersion": "5.1.0",
   "CanContainContent": false,
   "IsBetaVersion": false,
   "IsExperimentalVersion": false,
diff --git a/Source/SlateIconBrowser/Private/SlateIconBrowser.cpp b/Source/SlateIconBrowser/Private/SlateIconBrowser.cpp
index 3f5f0d9..8794960 100644
--- a/Source/SlateIconBrowser/Private/SlateIconBrowser.cpp
+++ b/Source/SlateIconBrowser/Private/SlateIconBrowser.cpp
@@ -16,7 +16,12 @@
 #include "WorkspaceMenuStructureModule.h"
 #include "Framework/Notifications/NotificationManager.h"
 #include "Styling/SlateStyleRegistry.h"
+
+#if ENGINE_MAJOR_VERSION == 5
 #include "Styling/UMGCoreStyle.h"
+#endif
+
+#include "SlateIconBrowserHacker.h"
 #include "Widgets/Input/SComboBox.h"
 #include "Widgets/Input/SEditableTextBox.h"
 #include "Widgets/Layout/SExpandableArea.h"
@@ -156,7 +161,7 @@ TSharedRef<SDockTab> FSlateIconBrowserModule::OnSpawnPluginTab(const FSpawnTabAr
 					.SelectionMode(ESelectionMode::Single)
 					.Visibility_Lambda([this]
 					{
-						return Lines.IsEmpty() ? EVisibility::Collapsed : EVisibility::Visible;
+						return Lines.Num() == 0 ? EVisibility::Collapsed : EVisibility::Visible;
 					})
 				]
 				+SVerticalBox::Slot()
@@ -166,7 +171,7 @@ TSharedRef<SDockTab> FSlateIconBrowserModule::OnSpawnPluginTab(const FSpawnTabAr
 					.HAlign(EHorizontalAlignment::HAlign_Center)
 					.Visibility_Lambda([this]
 					{
-						return Lines.IsEmpty() ? EVisibility::Visible : EVisibility::Collapsed;
+						return Lines.Num() == 0 ? EVisibility::Visible : EVisibility::Collapsed;
 					})
 					[
 						SNew(STextBlock)
@@ -176,18 +181,32 @@ TSharedRef<SDockTab> FSlateIconBrowserModule::OnSpawnPluginTab(const FSpawnTabAr
 			]
 			+SVerticalBox::Slot()
 			.VAlign(EVerticalAlignment::VAlign_Center)
+			.Padding(FMargin(0,4,0,0))
 			.AutoHeight()
 			[
 				SNew(SBorder)
-				.BorderImage(FAppStyle::Get().GetBrush("Brushes.Panel"))
+#if ENGINE_MAJOR_VERSION == 5
+				.BorderImage(EDITOR_STYLE_SAFE()::Get().GetBrush("Brushes.Panel"))
+#else
+				.BorderImage(EDITOR_STYLE_SAFE()::Get().GetBrush("ToolPanel.GroupBorder"))
+#endif
 				.Padding(FMargin(10, 5))
 				[
-					SAssignNew(CopyNoteTextBlock, STextBlock)
-					.Text_Lambda([&]
-					{
-						return FText::Format(LOCTEXT("CopyNote", "Double click a line to copy the {0} C++ code."),
-							GetCodeStyleText(GetConfig()->CopyCodeStyle));
-					})
+					SNew(SHorizontalBox)
+					+SHorizontalBox::Slot()
+					.AutoWidth()
+					[
+						SAssignNew(CopyNoteTextBlock, STextBlock)
+						.Font(FCoreStyle::GetDefaultFontStyle("Bold", 10))
+						.Text_Lambda([this]{ return GetCodeStyleText(GetConfig()->CopyCodeStyle); })
+					]
+					+SHorizontalBox::Slot()
+					.Padding(FMargin(4, 0))
+					.AutoWidth()
+					[
+						SNew(STextBlock)
+						.Text_Lambda([]{ return LOCTEXT("CopyNote", "Double click a line to copy"); })
+					]
 				]
 			]
 		];
@@ -278,7 +297,12 @@ void FSlateIconBrowserModule::FillHelpMenu(FMenuBuilder& MenuBuilder)
 		MenuBuilder.AddMenuEntry(
 			LOCTEXT("HelpDocumentation", "Documentation"),
 			LOCTEXT("HelpDocumentationTooltip", "Opens the documentation"),
+#if ENGINE_MAJOR_VERSION == 5
 			FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Documentation"),
+#else
+			FSlateIcon(FEditorStyle::GetStyleSetName(), "Icons.Documentation"),
+#endif
+			
 			FUIAction(
 				FExecuteAction::CreateLambda([=]
 				{
@@ -318,12 +342,17 @@ FString FSlateIconBrowserModule::TranslateDefaultStyleSets(FName StyleSet)
 void FSlateIconBrowserModule::FillDefaultStyleSetCodes()
 {
 #define STYLECODE(A, B) DefaultStyleSetCode.Add(FName(A), TEXT(B));
-	
+
+#if ENGINE_MAJOR_VERSION == 5
 	STYLECODE("EditorStyle", "FAppStyle::GetAppStyleSetName()");
 	STYLECODE("CoreStyle", "FAppStyle::GetAppStyleSetName()");
 	STYLECODE("UMGCoreStyle", "FUMGCoreStyle::Get().GetStyleSetName()");
+#else
+	STYLECODE("EditorStyle", "FEditorStyle::GetStyleSetName()")
+	STYLECODE("CoreStyle", "FCoreStyle::Get().GetStyleSetName()")
+	STYLECODE("UMGStyle", "FUMGStyle::GetStyleSetName()")
+#endif
 
-	;
 #undef STYLECODE
 }
 
@@ -338,17 +367,30 @@ void FSlateIconBrowserModule::CacheAllStyleNames()
 			return true;
 		}
 	);
+
+	AllStyles.Sort([](const TSharedPtr<FName>& A, const TSharedPtr<FName>& B)
+	{
+		const FString AString = A->ToString();
+		const FString BString = B->ToString();
+		return AString.Compare(BString) < 0;
+	});
 }
 
 void FSlateIconBrowserModule::CacheAllLines()
 {
 	const ISlateStyle* Style = FSlateStyleRegistry::FindSlateStyle(GetConfig()->SelectedStyle);
-	check(Style);
-	TSet<FName> keys = Style->GetStyleKeys();
+	const FSlateStyleSet* StyleSet = static_cast<const FSlateStyleSet*>(Style);
+	if (!StyleSet) { ensureMsgf(false, TEXT("Unexpected nullptr")); }
 
+#if ENGINE_MAJOR_VERSION == 5
+	TSet<FName> keys = Style->GetStyleKeys();
+#else
+	TSet<FName> keys = HackerMisc::GetStyleKeys(StyleSet);
+#endif
+	
 	AllLines.Empty(keys.Num());
 	AllLines.Reserve(keys.Num());
-
+	
 	for (FName key : keys) {
 		const FSlateBrush* brush = Style->GetOptionalBrush(key);
 		if (!brush || brush == FStyleDefaults::GetNoBrush())
@@ -371,7 +413,11 @@ void FSlateIconBrowserModule::CopyIconCodeToClipboard(FName Name, ECopyCodeStyle
 
 	FNotificationInfo Info(LOCTEXT("CopiedNotification", "C++ code copied to clipboard"));
 	Info.ExpireDuration = 3.f;
+#if ENGINE_MAJOR_VERSION == 5
 	Info.SubText = FText::FromString(CopyText);
+#else
+	Info.Text = FText::FromString(CopyText);
+#endif
 	FSlateNotificationManager::Get().AddNotification(Info);
 }
 
@@ -473,7 +519,9 @@ TSharedRef<ITableRow> FSlateIconBrowserModule::GenerateRow(TSharedPtr<FName> Nam
 			.Padding(FMargin(10, 5))
 			[
 				SNew(SImage)
+#if ENGINE_MAJOR_VERSION == 5
 				.DesiredSizeOverride(DesiredIconSize)
+#endif
 				.Image(Brush)
 			]
 		]
@@ -504,9 +552,17 @@ void FSlateIconBrowserModule::InputTextChanged(const FText& Text)
 void FSlateIconBrowserModule::MakeValidConfiguration()
 {
 	if (GetConfig()->SelectedStyle.IsNone())
+#if ENGINE_MAJOR_VERSION == 5
 		GetConfig()->SelectedStyle = FAppStyle::GetAppStyleSetName();
+#else
+		GetConfig()->SelectedStyle = FEditorStyle::GetStyleSetName();
+#endif
 }
 
 #undef LOCTEXT_NAMESPACE
-	
-IMPLEMENT_MODULE(FSlateIconBrowserModule, EditorIconBrowser)
\ No newline at end of file
+
+#if ENGINE_MAJOR_VERSION == 5
+IMPLEMENT_MODULE(FSlateIconBrowserModule, EditorIconBrowser)
+#else
+IMPLEMENT_MODULE(FSlateIconBrowserModule, SlateIconBrowser)
+#endif
diff --git a/Source/SlateIconBrowser/Private/SlateIconBrowserHacker.cpp b/Source/SlateIconBrowser/Private/SlateIconBrowserHacker.cpp
new file mode 100644
index 0000000..0f193db
--- /dev/null
+++ b/Source/SlateIconBrowser/Private/SlateIconBrowserHacker.cpp
@@ -0,0 +1,64 @@
+#include "SlateIconBrowserHacker.h"
+
+
+TSet<FName> HackerMisc::
+GetStyleKeys(const FSlateStyleSet* Style)
+{
+	TSet<FName> AllKeys;
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_WidgetStyleValues(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_FloatValues(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_Vector2DValues(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_ColorValues(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_SlateColorValues(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_MarginValues(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_BrushResources(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_Sounds(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	{
+		TArray<FName> Keys;
+		Hacker::Steal_FontInfoResources(Style)->GenerateKeyArray(Keys);
+		AllKeys.Append(Keys);
+	}
+
+	return AllKeys;
+}
diff --git a/Source/SlateIconBrowser/Private/SlateIconBrowserStyle.cpp b/Source/SlateIconBrowser/Private/SlateIconBrowserStyle.cpp
index 8c09a3f..68b94ab 100644
--- a/Source/SlateIconBrowser/Private/SlateIconBrowserStyle.cpp
+++ b/Source/SlateIconBrowser/Private/SlateIconBrowserStyle.cpp
@@ -5,9 +5,15 @@
 #include "Framework/Application/SlateApplication.h"
 #include "Slate/SlateGameResources.h"
 #include "Interfaces/IPluginManager.h"
-#include "Styling/SlateStyleMacros.h"
 
+#if ENGINE_MAJOR_VERSION == 5
+#include "Styling/SlateStyleMacros.h"
 #define RootToContentDir Style->RootToContentDir
+#else
+#define IMAGE_BRUSH( RelativePath, ... ) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ )
+#endif
+
+
 
 TSharedPtr<FSlateStyleSet> FSlateIconBrowserStyle::StyleInstance = nullptr;
 
@@ -41,8 +47,11 @@ TSharedRef< FSlateStyleSet > FSlateIconBrowserStyle::Create()
 	TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("SlateIconBrowserStyle"));
 	Style->SetContentRoot(IPluginManager::Get().FindPlugin("SlateIconBrowser")->GetBaseDir() / TEXT("Resources"));
 
+#if ENGINE_MAJOR_VERSION == 5
 	Style->Set("SlateIconBrowser.Icon", new IMAGE_BRUSH_SVG(TEXT("Icon"), Icon20x20));
-
+#else
+	Style->Set("SlateIconBrowser.Icon", new IMAGE_BRUSH(TEXT("Icon128"), Icon20x20));
+#endif
 	return Style;
 }
 
diff --git a/Source/SlateIconBrowser/Public/SlateIconBrowser.h b/Source/SlateIconBrowser/Public/SlateIconBrowser.h
index 9280038..51cb629 100644
--- a/Source/SlateIconBrowser/Public/SlateIconBrowser.h
+++ b/Source/SlateIconBrowser/Public/SlateIconBrowser.h
@@ -15,6 +15,14 @@ class STextBlock;
 template<typename T> class SListView;
 template<typename T> class SComboBox;
 
+
+#if ENGINE_MAJOR_VERSION == 4
+#define EDITOR_STYLE_SAFE() FEditorStyle
+#else
+#define EDITOR_STYLE_SAFE() FAppStyle
+#endif
+
+
 class FSlateIconBrowserModule : public IModuleInterface
 {
 public:
diff --git a/Source/SlateIconBrowser/Public/SlateIconBrowserHacker.h b/Source/SlateIconBrowser/Public/SlateIconBrowserHacker.h
new file mode 100644
index 0000000..43ab186
--- /dev/null
+++ b/Source/SlateIconBrowser/Public/SlateIconBrowserHacker.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "Styling/SlateStyle.h"
+
+
+#define DECLARE_THIEF_FUNCTION(Class, MemberType, MemberName)\
+	template <MemberType Class::* MEMBER_PTR>\
+	struct GenerateThiefFunction_##MemberName{\
+		friend MemberType* Steal_##MemberName(Class* Victim)       { return &(Victim->*MEMBER_PTR); }\
+		friend MemberType* Steal_##MemberName(Class& Victim)       { return &(Victim.*MEMBER_PTR);  }\
+		friend MemberType* Steal_##MemberName(const Class* Victim) { return &(const_cast<Class*>(Victim)->*MEMBER_PTR);  }\
+		friend MemberType* Steal_##MemberName(const Class& Victim) { return &(const_cast<Class&>(Victim).*MEMBER_PTR);   }\
+	};\
+	template struct GenerateThiefFunction_##MemberName<&Class::MemberName>;\
+	MemberType* Steal_##MemberName(Class* Victim);\
+	template struct GenerateThiefFunction_##MemberName<&Class::MemberName>;\
+	MemberType* Steal_##MemberName(Class& Victim);\
+	template struct GenerateThiefFunction_##MemberName<&Class::MemberName>;\
+	MemberType* Steal_##MemberName(const Class* Victim);\
+	template struct GenerateThiefFunction_##MemberName<&Class::MemberName>;\
+	MemberType* Steal_##MemberName(const Class& Victim);
+
+
+namespace Hacker
+{
+	typedef TMap<FName, TSharedRef<FSlateWidgetStyle>> FWidgetStyleValuesMap;
+	typedef TMap<FName, float> FFloatValuesMap;
+	typedef TMap<FName, FVector2D> FVector2DValuesMap;
+	typedef TMap<FName, FLinearColor> FFColorValuesMap;
+	typedef TMap<FName, FSlateColor> FSlateColorValuesMap;
+	typedef TMap<FName, FMargin> FMarginValuesMap;
+	typedef TMap<FName, FSlateBrush*> FBrushResourcesMap;
+	typedef TMap<FName, FSlateSound> FSoundsMap;
+	typedef TMap<FName, FSlateFontInfo> FFontInfoResourcesMap;
+
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FWidgetStyleValuesMap, WidgetStyleValues)
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FFloatValuesMap, FloatValues)
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FVector2DValuesMap, Vector2DValues)
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FFColorValuesMap, ColorValues)
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FSlateColorValuesMap, SlateColorValues)
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FMarginValuesMap, MarginValues)
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FBrushResourcesMap, BrushResources)
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FSoundsMap, Sounds)
+	DECLARE_THIEF_FUNCTION(FSlateStyleSet, FFontInfoResourcesMap, FontInfoResources)
+}
+
+
+namespace HackerMisc
+{
+	TSet<FName> GetStyleKeys(const FSlateStyleSet* Style);
+}
+
+#undef DECLARE_THIEF_FUNCTION
\ No newline at end of file
diff --git a/Source/SlateIconBrowser/Public/SlateIconBrowserUserSettings.h b/Source/SlateIconBrowser/Public/SlateIconBrowserUserSettings.h
index f0ed3cb..6b7a615 100644
--- a/Source/SlateIconBrowser/Public/SlateIconBrowserUserSettings.h
+++ b/Source/SlateIconBrowser/Public/SlateIconBrowserUserSettings.h
@@ -20,7 +20,9 @@ class USlateIconBrowserUserSettings : public UObject
 	GENERATED_BODY()
 	
 public:
-	UPROPERTY(Config)
+	// I think there is no need to make filter string serialized by config
+	// This makes it cumbersome if I open IconBrowser next time but I just want to search another Brush
+	UPROPERTY()
 	FString FilterString;
 
 	UPROPERTY(Config)
diff --git a/Source/SlateIconBrowser/SlateIconBrowser.Build.cs b/Source/SlateIconBrowser/SlateIconBrowser.Build.cs
index 5c7fcef..fa60e2e 100644
--- a/Source/SlateIconBrowser/SlateIconBrowser.Build.cs
+++ b/Source/SlateIconBrowser/SlateIconBrowser.Build.cs
@@ -36,7 +36,11 @@ public SlateIconBrowser(ReadOnlyTargetRules Target) : base(Target)
 			{
 				"Projects",
 				"InputCore",
+				
+#if UE_5_0_OR_LATER
 				"EditorFramework",
+#endif
+				
 				"UnrealEd",
 				"CoreUObject",
 				"Engine",

From 6ef238576bcc90d036295f99d252953f20cc3ea9 Mon Sep 17 00:00:00 2001
From: Periokumene <116148983+Periokumene@users.noreply.github.com>
Date: Fri, 19 Jul 2024 12:40:25 +0800
Subject: [PATCH 2/2] Reset FilterString when quitting SlateIconBrowser Tab

---
 Source/SlateIconBrowser/Private/SlateIconBrowser.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Source/SlateIconBrowser/Private/SlateIconBrowser.cpp b/Source/SlateIconBrowser/Private/SlateIconBrowser.cpp
index 8794960..221d4b0 100644
--- a/Source/SlateIconBrowser/Private/SlateIconBrowser.cpp
+++ b/Source/SlateIconBrowser/Private/SlateIconBrowser.cpp
@@ -58,6 +58,10 @@ TSharedRef<SDockTab> FSlateIconBrowserModule::OnSpawnPluginTab(const FSpawnTabAr
 	CacheAllLines();
 
 	return SNew(SDockTab)
+		.OnTabClosed_Lambda([](TSharedRef<SDockTab>)
+		{
+			GetMutableDefault<USlateIconBrowserUserSettings>()->FilterString = TEXT("");
+		})
 		.TabRole(ETabRole::NomadTab)
 		[
 			// Put your tab content here!