From d7b0e0977976925aaca1f83bb481b6e2d023daa2 Mon Sep 17 00:00:00 2001
From: camila314 <47485054+camila314@users.noreply.github.com>
Date: Thu, 16 Mar 2023 19:42:30 -0500
Subject: [PATCH] mouse and file picker impl for mac

---
 .gitignore                           |   1 +
 loader/src/platform/mac/util.mm      | 123 +++++++++++++++++++++------
 loader/src/platform/windows/util.cpp |  10 +++
 loader/src/utils/cocos.cpp           |  14 ---
 4 files changed, 106 insertions(+), 42 deletions(-)

diff --git a/.gitignore b/.gitignore
index a2f4c8ff..78fb94ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,6 +40,7 @@
 # Ignore build folders
 **/build
 build
+build2
 build-docs/
 bin
 
diff --git a/loader/src/platform/mac/util.mm b/loader/src/platform/mac/util.mm
index 374ac092..29d7280d 100644
--- a/loader/src/platform/mac/util.mm
+++ b/loader/src/platform/mac/util.mm
@@ -8,6 +8,7 @@ using namespace geode::prelude;
 #import <AppKit/AppKit.h>
 #include <Geode/utils/web.hpp>
 #include <Geode/utils/file.hpp>
+#include <Geode/utils/cocos.hpp>
 
 bool utils::clipboard::write(std::string const& data) {
     [[NSPasteboard generalPasteboard] clearContents];
@@ -36,47 +37,113 @@ void utils::web::openLinkInBrowser(std::string const& url) {
         openURL:[NSURL URLWithString:[NSString stringWithUTF8String:url.c_str()]]];
 }
 
-// @interface FileDialog : NSObject
-// + (Result<ghc::filesystem::path>)importDocumentWithMode:(file::PickMode)mode
-// options:(file::FilePickOptions const&)options;
-// + (Result<std::vector<ghc::filesystem::path>>)importDocumentsWithOptions:(file::FilePickOptions
-// const&)options
-// @end
+/*@interface FileDialog : NSObject
++ (Result<ghc::filesystem::path>)importDocumentWithMode:(file::PickMode)mode options:(file::FilePickOptions const&)options mult:(bool)mult;
++ (Result<std::vector<ghc::filesystem::path>>)importDocumentsWithOptions:(file::FilePickOptions const&)options;
+@end
 
-// @implementation FileDialog
+@implementation FileDialog
 
-// + (Result<ghc::filesystem::path>)importDocumentWithMode:(file::PickMode)mode
-// options:(file::FilePickOptions const&)options { 	NSOpenPanel* panel = [NSOpenPanel
-// openPanel];
-// 	// TODO: [panel setAllowedFileTypes:@[]];
++ (Result<ghc::filesystem::path>)importDocumentWithMode:(file::PickMode)mode options:(file::FilePickOptions const&)options mult:(bool)mult {
+    NSOpenPanel* panel = [NSOpenPanel openPanel];
+    // TODO: [panel setAllowedFileTypes:@[]];
 
-// 	auto defaultPath = [NSString stringWithCString:options.defaultPath.c_str()
-// encoding:NSUTF8StringEncoding]; 	[panel setDirectoryURL: [NSURL fileURLWithPath:
-// defaultPath]]; 	[panel beginWithCompletionHandler:^(NSInteger result){ 		if (result ==
-// NSFileHandlingPanelOKButton) { 			auto fileUrl = [[panel URLs] objectAtIndex:0]; 			auto path =
-// std::string([[fileUrl path] UTF8String], [[fileUrl path]
-// lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); 			return Ok(path);
-// 		}
-// 		else {
-// 			return Err(result);
-// 		}
-// 	}];
-// }
+    if (options.defaultPath) {
+        auto defaultPath = [NSString stringWithCString:options.defaultPath->c_str() encoding:NSUTF8StringEncoding];
+        [panel setDirectoryURL: [NSURL fileURLWithPath: defaultPath]];
+    }
 
-// @end
+    panel.allowsMultipleSelection = mult;
+
+    int result = [panel runModal];
+    if (result == NSFileHandlingPanelOKButton) {
+        auto fileUrl = [[panel URLs] objectAtIndex:0];
+        auto path = std::string([[fileUrl path] UTF8String], [[fileUrl path] lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
+        return Ok(ghc::filesystem::path(path));
+    } else {
+        return Err(result);
+    }
+}
+
+@end*/
+
+
+@interface FileDialog : NSObject
++(Result<std::vector<ghc::filesystem::path>>) filePickerWithMode:(file::PickMode)mode options:(file::FilePickOptions const&)options multiple:(bool)mult;
+@end
+
+@implementation FileDialog
++(Result<std::vector<ghc::filesystem::path>>) filePickerWithMode:(file::PickMode)mode options:(file::FilePickOptions const&)options multiple:(bool)mult {
+    NSOpenPanel* panel = [NSOpenPanel openPanel];
+
+    // allowed files
+    NSMutableArray* allowed;
+
+    for (auto& f : options.filters) {
+        for (auto& i : f.files) {
+            auto nsstr = [NSString stringWithUTF8String: i.c_str()];
+
+            if (![allowed containsObject: nsstr])
+                [allowed addObject: nsstr];
+        }
+    }
+
+    if (options.filters.size())
+        [panel setAllowedFileTypes: allowed];
+
+    // multiple
+    [panel setAllowsMultipleSelection: mult];
+
+    // default path
+    if (options.defaultPath) {
+        auto defaultPath = [NSString stringWithUTF8String:options.defaultPath->c_str()];
+        [panel setDirectoryURL: [NSURL URLWithString: defaultPath]];
+    }
+
+    // other
+    [panel setCanChooseDirectories: NO];
+    [panel setCanChooseFiles: YES];
+
+    // run thing
+
+    int result = [panel runModal];
+
+    if (result == NSFileHandlingPanelOKButton) {
+        std::vector<ghc::filesystem::path> fileURLs;
+
+        for (NSURL* i in panel.URLs) {
+            fileURLs.push_back(std::string(i.path.UTF8String));
+        }
+
+        return Ok(fileURLs);
+    } else {
+        return Err("File picker cancelled");
+    }
+}
+@end
 
 Result<ghc::filesystem::path> utils::file::pickFile(
     file::PickMode mode, file::FilePickOptions const& options
 ) {
-    return Err<std::string>("utils::file::pickFile is not implemented");
-    // return [FileDialog importDocumentWithMode:mode options:options];
+    auto result = [FileDialog filePickerWithMode:mode options:options multiple: false];
+
+    if (result.isOk()) {
+        return Ok<ghc::filesystem::path>(std::move(result.unwrap()[0]));
+    } else {
+        return Err<>(result.unwrapErr());
+    }
 }
 
 Result<std::vector<ghc::filesystem::path>> utils::file::pickFiles(
     file::FilePickOptions const& options
 ) {
-    return Err("utils::file::pickFiles is not implemented");
-    // return [FileDialog importDocumentWithOptions:options];
+    //return Err("utils::file::pickFiles is not implemented");
+    return [FileDialog filePickerWithMode: file::PickMode::OpenFile options:options multiple:true];
+}
+
+CCPoint cocos::getMousePos() {
+    auto mouse = [NSEvent mouseLocation];
+    return ccp(mouse.x, mouse.y);
 }
 
 #endif
diff --git a/loader/src/platform/windows/util.cpp b/loader/src/platform/windows/util.cpp
index 8300d451..0a4adeb6 100644
--- a/loader/src/platform/windows/util.cpp
+++ b/loader/src/platform/windows/util.cpp
@@ -13,6 +13,7 @@ using namespace geode::prelude;
 #include <shobjidl.h>
 #include <sstream>
 #include <Geode/utils/web.hpp>
+#include <Geode/utils/cocos.hpp>
 
 bool utils::clipboard::write(std::string const& data) {
     if (!OpenClipboard(nullptr)) return false;
@@ -105,4 +106,13 @@ void utils::web::openLinkInBrowser(std::string const& url) {
     ShellExecuteA(0, 0, url.c_str(), 0, 0, SW_SHOW);
 }
 
+CCPoint cocos::getMousePos() {
+    auto* director = CCDirector::get();
+    auto* gl = director->getOpenGLView();
+    auto winSize = director->getWinSize();
+    auto frameSize = gl->getFrameSize();
+    auto mouse = gl->getMousePosition() / frameSize;
+    return ccp(mouse.x, 1.f - mouse.y) * winSize;
+}
+
 #endif
diff --git a/loader/src/utils/cocos.cpp b/loader/src/utils/cocos.cpp
index 10c2a9bd..977d4c1f 100644
--- a/loader/src/utils/cocos.cpp
+++ b/loader/src/utils/cocos.cpp
@@ -330,20 +330,6 @@ CCScene* geode::cocos::switchToScene(CCLayer* layer) {
     return scene;
 }
 
-CCPoint geode::cocos::getMousePos() {
-#ifdef GEODE_IS_WINDOWS
-    auto* director = CCDirector::get();
-    auto* gl = director->getOpenGLView();
-    auto winSize = director->getWinSize();
-    auto frameSize = gl->getFrameSize();
-    auto mouse = gl->getMousePosition() / frameSize;
-    return ccp(mouse.x, 1.f - mouse.y) * winSize;
-#else
-    // TODO: implement this for mac
-    return ccp(0, 0);
-#endif
-}
-
 static CreateLayerFunc LOADING_FINISHED_SCENE = nullptr;
 
 void geode::cocos::reloadTextures(CreateLayerFunc returnTo) {