Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions hxd/DropFileEvent.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package hxd;

import haxe.ds.ReadOnlyArray;
import haxe.io.Bytes;

/**
The information about the dropped file.
**/
abstract class DroppedFile {
/**
The dropped file name/path.
**/
public var file(default, null) : String;
#if js
/**
The native JS data transfer file.
**/
public var native(default, null) : js.html.File;

#end

public function new( file : String ) {
this.file = file;
}


/**
Retrieve the dropped file contents asynchronously and pass it to `callback`.
**/
abstract public function getBytes( callback : (data : Bytes) -> Void ) : Void;
}

/**
The drag&drop operation event.

@see `hxd.Window.addDragAndDropTarget`
@see `hxd.Window.removeDragAndDropTarget`
**/
class DropFileEvent {
/**
The list of the files that were dropped.

Only guaranteed to be populated when `kind == Drop`.
**/
public var files(default, null): ReadOnlyArray<DroppedFile>;
/**
The first dropped file. Alias to `files[0]`.
**/
public var file(get, never): Null<DroppedFile>;
/**
The X position inside the window at which the file was dropped.
**/
public var dropX(default, null): Int;
/**
The Y position inside the window at which the file was dropped.
**/
public var dropY(default, null): Int;

public function new( files : Array<DroppedFile>, dx : Int, dy : Int ) {
this.files = files;
this.dropX = dx;
this.dropY = dy;
}

inline function get_file() return files[0];

}

57 changes: 57 additions & 0 deletions hxd/Window.hl.hx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@ typedef DisplaySetting = {
framerate : Int
}

private class NativeDroppedFile extends hxd.DropFileEvent.DroppedFile {
public function getBytes( callback : ( data : haxe.io.Bytes ) -> Void ) {
haxe.Timer.delay(() -> callback(sys.io.File.getBytes(file)), 1);
}
}

//@:coreApi
class Window {

var resizeEvents : List<Void -> Void>;
var eventTargets : List<Event -> Void>;
var dropTargets : List<DropFileEvent -> Void>;
var dropFiles : Array<hxd.DropFileEvent.DroppedFile>;

public var width(get, never) : Int;
public var height(get, never) : Int;
Expand Down Expand Up @@ -92,6 +100,7 @@ class Window {
this.windowHeight = height;
eventTargets = new List();
resizeEvents = new List();
dropTargets = new List();
#if hlsdl
var sdlFlags = if (!fixed) sdl.Window.SDL_WINDOW_SHOWN | sdl.Window.SDL_WINDOW_RESIZABLE else sdl.Window.SDL_WINDOW_SHOWN;
#if heaps_vulkan
Expand Down Expand Up @@ -168,6 +177,32 @@ class Window {
for( f in resizeEvents ) f();
}

public function addDragAndDropTarget( f : ( event : DropFileEvent ) -> Void ) : Void {
if (dropTargets.length == 0) {
#if (hlsdl >= version("1.14.0"))
sdl.Sdl.setDragAndDropEnabled(true);
#elseif (hldx >= version("1.14.0"))
window.dragAndDropEnabled = true;
#end
}
dropTargets.push(f);
}

public function removeDragAndDropTarget( f : ( event : DropFileEvent ) -> Void ) : Void {
for( e in dropTargets )
if( Reflect.compareMethods(e, f) ) {
dropTargets.remove(f);
break;
}
if ( dropTargets.length == 0 ) {
#if (hlsdl >= version("1.14.0"))
sdl.Sdl.setDragAndDropEnabled(false);
#elseif (hldx >= version("1.14.0"))
window.dragAndDropEnabled = false;
#end
}
}

public function setCursorPos( x : Int, y : Int, emitEvent : Bool = false ) : Void {
#if hldx
if (mouseMode == Absolute) window.setCursorPosition(x, y);
Expand Down Expand Up @@ -439,6 +474,7 @@ class Window {
#end
eh = new Event(ERelease, e.mouseX, e.mouseY);
eh.touchId = e.fingerId;

#elseif hldx
case KeyDown:
eh = new Event(EKeyDown);
Expand All @@ -458,6 +494,27 @@ class Window {
eh = new Event(ETextInput, mouseX, mouseY);
eh.charCode = e.keyCode;
#end
#if (hlsdl >= version("1.14.0") || hldx >= version("1.14.0"))
case DropStart:
dropFiles = [];
case DropFile:
#if hlsdl
dropFiles.push(new NativeDroppedFile(@:privateAccess String.fromUTF8(e.dropFile)));
#else
dropFiles.push(new NativeDroppedFile(@:privateAccess String.fromUCS2(e.dropFile)));
#end
case DropEnd:
var event = new DropFileEvent(
dropFiles,
#if hldx
e.mouseX, e.mouseY
#else
mouseX, mouseY
#end
);
for ( dt in dropTargets ) dt(event);
dropFiles = null;
#end
case Quit:
return onClose();
default:
Expand Down
12 changes: 12 additions & 0 deletions hxd/Window.hx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ class Window {
public function resize( width : Int, height : Int ) : Void {
}

/**
Add a drag&drop events callback.
**/
public function addDragAndDropTarget( f : ( event : DropFileEvent ) -> Void ) : Void {
}

/**
Remove a drag&drop events callback.
**/
public function removeDragAndDropTarget( f : ( event : DropFileEvent ) -> Void ) : Void {
}

@:deprecated("Use the displayMode property instead")
public function setFullScreen( v : Bool ) : Void {
}
Expand Down
52 changes: 52 additions & 0 deletions hxd/Window.js.hx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,27 @@ enum DisplayMode {
FullscreenResize;
}

private class NativeDroppedFile extends hxd.DropFileEvent.DroppedFile {

public function new( native : js.html.File ) {
super(native.name);
this.native = native;
}

public function getBytes( callback : ( data : haxe.io.Bytes ) -> Void ) {
var reader = new js.html.FileReader();
reader.onload = (_) -> callback(haxe.io.Bytes.ofData(reader.result));
reader.onerror = (_) -> callback(null);
reader.readAsArrayBuffer(native);
}

}

class Window {

var resizeEvents : List<Void -> Void>;
var eventTargets : List<Event -> Void>;
var dropTargets : List<DropFileEvent -> Void>;

public var width(get, never) : Int;
public var height(get, never) : Int;
Expand Down Expand Up @@ -69,6 +86,7 @@ class Window {
var customCanvas = canvas != null;
eventTargets = new List();
resizeEvents = new List();
dropTargets = new List();

if( !js.Browser.supported ) {
canvasPos = { "width":0, "top":0, "left":0, "height":0 };
Expand Down Expand Up @@ -221,6 +239,40 @@ class Window {
public function resize( width : Int, height : Int ) : Void {
}

public function addDragAndDropTarget( f : ( event : DropFileEvent ) -> Void ) : Void {
if( dropTargets.length == 0 ) {
var element = canvas; // Probably should adhere to `globalEvents`?
element.addEventListener("dragover", handleDragAndDropEvent);
element.addEventListener("drop", handleDragAndDropEvent);
}
dropTargets.add(f);
}

public function removeDragAndDropTarget( f : ( event : DropFileEvent ) -> Void ) : Void {
for( e in dropTargets )
if( Reflect.compareMethods(e, f) ) {
dropTargets.remove(f);
break;
}
if( dropTargets.length == 0 ) {
var element = canvas; // Probably should adhere to `globalEvents`?
element.removeEventListener("dragover", handleDragAndDropEvent);
element.removeEventListener("drop", handleDragAndDropEvent);
}
}

function handleDragAndDropEvent( e : js.html.DragEvent ) {
e.preventDefault();
if ( e.type == "dragover" || e.dataTransfer == null || e.dataTransfer.files.length == 0 ) return;
var ev = new DropFileEvent([
for ( file in e.dataTransfer.files ) new NativeDroppedFile(file)
],
Math.round((e.clientX - canvasPos.left) * getPixelRatio()),
Math.round((e.clientY - canvasPos.top) * getPixelRatio())
);
for( dt in dropTargets ) dt(ev);
}

@:deprecated("Use the displayMode property instead")
public function setFullScreen( v : Bool ) : Void {
var doc = js.Browser.document;
Expand Down