Add initial file watcher API

This commit is contained in:
Joshua Granick
2017-09-25 16:46:58 -07:00
parent 74fc7deb09
commit 0bdeee533d
6 changed files with 316 additions and 0 deletions

View File

@@ -49,6 +49,10 @@ class NativeCFFI {
@:cffi private static function lime_data_pointer_offset (dataPointer:DataPointer, offset:Int):Float;
@:cffi private static function lime_deflate_compress (data:Dynamic, bytes:Dynamic):Dynamic;
@:cffi private static function lime_deflate_decompress (data:Dynamic, bytes:Dynamic):Dynamic;
@:cffi private static function lime_directory_watcher_create (callback:Dynamic):CFFIPointer;
@:cffi private static function lime_directory_watcher_add_watch (handle:CFFIPointer, path:Dynamic, recursive:Bool):Dynamic;
@:cffi private static function lime_directory_watcher_remove_watch (handle:CFFIPointer, watchID:Dynamic):Void;
@:cffi private static function lime_directory_watcher_update (handle:CFFIPointer):Void;
@:cffi private static function lime_drop_event_manager_register (callback:Dynamic, eventObject:Dynamic):Void;
@:cffi private static function lime_file_dialog_open_directory (title:String, filter:String, defaultPath:String):Dynamic;
@:cffi private static function lime_file_dialog_open_file (title:String, filter:String, defaultPath:String):Dynamic;

View File

@@ -0,0 +1,129 @@
package lime.system;
import lime._backend.native.NativeCFFI;
import lime.app.Application;
import lime.app.Event;
#if !lime_debug
@:fileXml('tags="haxe,release"')
@:noDebug
#end
@:access(lime._backend.native.NativeCFFI)
class DirectoryWatcher {
public var onChange = new Event<Void->Void> ();
public var onFileAdd = new Event<String->Void> ();
public var onFileModify = new Event<String->Void> ();
public var onFileRemove = new Event<String->Void> ();
private var handle:CFFIPointer;
private var hasUpdate:Bool;
private var ids:Map<String, Int>;
public function new () {
#if (lime_cffi && !macro)
handle = NativeCFFI.lime_directory_watcher_create (this_onChange);
ids = new Map ();
#end
}
public function addPath (path:String, recursive:Bool = true):Void {
#if (lime_cffi && !macro)
if (!hasUpdate) {
Application.current.onUpdate.add (this_onUpdate);
hasUpdate = true;
}
var id:Int = NativeCFFI.lime_directory_watcher_add_watch (handle, path, recursive);
ids[path] = id;
#end
}
public function removePath (path:String):Void {
#if (lime_cffi && !macro)
if (ids.exists (path)) {
NativeCFFI.lime_directory_watcher_remove_watch (handle, ids[path]);
ids.remove (path);
if (!ids.keys ().hasNext ()) {
Application.current.onUpdate.remove (this_onUpdate);
hasUpdate = false;
}
}
#end
}
private function this_onChange (directory:String, file:String, action:Int):Void {
var trailingSlash = (directory.substr (-1) == "/" || directory.substr (-1) == "\\");
var startingSlash = (file.substr (0, 1) == "/" || file.substr (0, 1) == "\\");
var path;
if (trailingSlash && startingSlash) {
path = directory + file.substr (1);
} else if (!trailingSlash && !startingSlash) {
path = directory + #if windows "\\" #else "/" #end + file;
} else {
path = directory + file;
}
switch (action) {
case 1:
onFileAdd.dispatch (path);
onChange.dispatch ();
case 2:
onFileRemove.dispatch (path);
onChange.dispatch ();
case 4:
onFileModify.dispatch (path);
onChange.dispatch ();
}
}
private function this_onUpdate (_):Void {
#if (lime_cffi && !macro)
NativeCFFI.lime_directory_watcher_update (handle);
#end
}
}

View File

@@ -219,6 +219,8 @@
<compilerflag value="-I${NATIVE_TOOLKIT_PATH}/simplefilewatcher/include/" />
<compilerflag value="-DLIME_SIMPLEFILEWATCHER" />
<file name="src/system/DirectoryWatcher.cpp" />
</section>
<section if="LIME_TINYFILEDIALOGS">

View File

@@ -0,0 +1,38 @@
#ifndef LIME_SYSTEM_DIRECTORY_WATCHER_H
#define LIME_SYSTEM_DIRECTORY_WATCHER_H
#include <hx/CFFI.h>
#include <map>
#include <string>
namespace lime {
class DirectoryWatcher {
public:
DirectoryWatcher (value callback);
~DirectoryWatcher ();
unsigned long AddWatch (const std::string directory, bool recursive);
void RemoveWatch (unsigned long watchID);
void Update ();
AutoGCRoot* callback;
private:
void* fileWatcher = 0;
std::map<unsigned long, void*> watchListeners;
};
}
#endif

View File

@@ -23,6 +23,7 @@
#include <system/CFFIPointer.h>
#include <system/Clipboard.h>
#include <system/ClipboardEvent.h>
#include <system/DirectoryWatcher.h>
#include <system/Endian.h>
#include <system/JNI.h>
#include <system/Locale.h>
@@ -64,6 +65,14 @@ namespace lime {
}
void gc_directory_watcher (value handle) {
DirectoryWatcher* watcher = (DirectoryWatcher*)val_data (handle);
delete watcher;
}
void gc_font (value handle) {
#ifdef LIME_FREETYPE
@@ -349,6 +358,50 @@ namespace lime {
}
value lime_directory_watcher_create (value callback) {
#ifdef LIME_SIMPLEFILEWATCHER
DirectoryWatcher* watcher = new DirectoryWatcher (callback);
return CFFIPointer (watcher, gc_directory_watcher);
#else
return alloc_null ();
#endif
}
value lime_directory_watcher_add_watch (value handle, value path, bool recursive) {
#ifdef LIME_SIMPLEFILEWATCHER
DirectoryWatcher* watcher = (DirectoryWatcher*)val_data (handle);
return alloc_int (watcher->AddWatch (val_string (path), recursive));
#else
return alloc_int (0);
#endif
}
void lime_directory_watcher_remove_watch (value handle, value watchID) {
#ifdef LIME_SIMPLEFILEWATCHER
DirectoryWatcher* watcher = (DirectoryWatcher*)val_data (handle);
watcher->RemoveWatch (val_int (watchID));
#endif
}
void lime_directory_watcher_update (value handle) {
#ifdef LIME_SIMPLEFILEWATCHER
DirectoryWatcher* watcher = (DirectoryWatcher*)val_data (handle);
watcher->Update ();
#endif
}
void lime_drop_event_manager_register (value callback, value eventObject) {
DropEvent::callback = new AutoGCRoot (callback);
@@ -1833,6 +1886,10 @@ namespace lime {
DEFINE_PRIME2 (lime_data_pointer_offset);
DEFINE_PRIME2 (lime_deflate_compress);
DEFINE_PRIME2 (lime_deflate_decompress);
DEFINE_PRIME1 (lime_directory_watcher_create);
DEFINE_PRIME3 (lime_directory_watcher_add_watch);
DEFINE_PRIME2v (lime_directory_watcher_remove_watch);
DEFINE_PRIME1v (lime_directory_watcher_update);
DEFINE_PRIME2v (lime_drop_event_manager_register);
DEFINE_PRIME3 (lime_file_dialog_open_directory);
DEFINE_PRIME3 (lime_file_dialog_open_file);

View File

@@ -0,0 +1,86 @@
#include <system/DirectoryWatcher.h>
#include <FileWatcher/FileWatcher.h>
namespace lime {
class UpdateListener : public FW::FileWatchListener {
public:
UpdateListener (DirectoryWatcher* _watcher) {
watcher = _watcher;
}
void handleFileAction (FW::WatchID watchid, const FW::String& dir, const FW::String& filename, FW::Action action) {
value callback = watcher->callback->get ();
val_call3 (callback, alloc_string (dir.c_str ()), alloc_string (filename.c_str ()), alloc_int (action));
}
DirectoryWatcher* watcher;
};
DirectoryWatcher::DirectoryWatcher (value _callback) {
callback = new AutoGCRoot (_callback);
fileWatcher = new FW::FileWatcher ();
}
DirectoryWatcher::~DirectoryWatcher () {
delete callback;
delete fileWatcher;
std::map<unsigned long, void*>::iterator it;
for (it = watchListeners.begin (); it != watchListeners.end (); it++) {
delete (UpdateListener*)watchListeners[it->first];
}
}
unsigned long DirectoryWatcher::AddWatch (std::string directory, bool recursive) {
UpdateListener* listener = new UpdateListener (this);
FW::WatchID watchID = ((FW::FileWatcher*)fileWatcher)->addWatch (directory, listener, true);
watchListeners[watchID] = listener;
return watchID;
}
void DirectoryWatcher::RemoveWatch (unsigned long watchID) {
((FW::FileWatcher*)fileWatcher)->removeWatch (watchID);
if (watchListeners.find (watchID) != watchListeners.end ()) {
delete (UpdateListener*)watchListeners[watchID];
watchListeners.erase (watchID);
}
}
void DirectoryWatcher::Update () {
((FW::FileWatcher*)fileWatcher)->update ();
}
}