diff --git a/std/hl/UI.hx b/std/hl/UI.hx index 847d7466506..e0a26e1ac22 100644 --- a/std/hl/UI.hx +++ b/std/hl/UI.hx @@ -22,6 +22,8 @@ package hl; +import haxe.io.Path; + typedef SentinelHandle = hl.Abstract<"ui_sentinel">; abstract Sentinel(SentinelHandle) { @@ -134,6 +136,11 @@ typedef FileOptions = { var ?title:String; } +typedef MultipleFileResult = { + var path: String; + var files: Array; +} + /** These are the bindings for the HL `ui.hdll` library, which contains some low level system access. **/ @@ -168,11 +175,15 @@ class UI { return chooseFile(false, opts); } + public static function loadFileMultiple(opts:FileOptions) { + return chooseFileMultiple(opts); + } + public static function saveFile(opts:FileOptions) { return chooseFile(true, opts); } - static function chooseFile(save:Bool, opts:FileOptions) @:privateAccess { + static function chooseFileOpts(save: Bool, opts: FileOptions, multiple=false ) @:privateAccess { var out:Dynamic = {}; if (opts.fileName != null) { var file = sys.FileSystem.absolutePath(opts.fileName); @@ -206,15 +217,57 @@ class UI { } if (opts.window != null) out.window = opts.window.h; - var str = _chooseFile(save, out); + if( multiple ) + out.multiple = true; + + return out; + } + + static function chooseFile(save:Bool, opts:FileOptions) @:privateAccess { + var str = _chooseFile(save, chooseFileOpts(save, opts) ); return str == null ? null : String.fromUCS2(str); } + static function chooseFileMultiple(opts:FileOptions) : MultipleFileResult @:privateAccess { + var loadOpts = chooseFileOpts(false, opts); + loadOpts.multiple = true; + var bytes = _chooseFile(false, loadOpts ); + if( bytes == null ) + return null; + + var path = null; + var files = []; + var idx = 0; + var len = bytes.ucs2Length(idx); + + while( len > 0 ) { + var str = String.fromUCS2( bytes.sub(idx, len * 2 + 2 ) ); + if( path == null ) + path = str; + else + files.push( str ); + idx += len * 2 + 2; + len = bytes.ucs2Length(idx); + } + + // Special case: If only one file is returned, it will be added to path. Separate it out + // here for API consistency + if( files.length == 0 ) { + files.push( Path.withoutDirectory( path ) ); + path = Path.directory( path ); + } + + return { + path: path, + files: files + }; + } + @:hlNative("ui", "ui_choose_file") static function _chooseFile(forSave:Bool, obj:Dynamic):hl.Bytes { return null; } - + #if (hl_ver >= version("1.12.0")) public static function setClipboardText(text:String):Bool { if(text == null) @@ -246,5 +299,5 @@ class UI { return null; } #end - + }