Browse Source

Add support for file drag drop

disarray2077 3 years ago
parent
commit
6d2803dbb1

+ 12 - 3
BeefLibs/Beefy2D/src/BFWindow.bf

@@ -48,6 +48,7 @@ namespace Beefy
 			ShowMinimized = 0x0200'0000,
 			ShowMaximized = 0x0400'0000,
 			AllowFullscreen = 0x0800'0000,
+			AcceptFiles = 0x1000'0000
         };
 
 		[AllowDuplicates]
@@ -127,7 +128,8 @@ namespace Beefy
         delegate void NativeMouseUpDelegate(void* window, int32 x, int32 y, int32 btn);
         delegate void NativeMouseWheelDelegate(void* window, int32 x, int32 y, float deltaX, float deltaY);
         delegate void NativeMouseLeaveDelegate(void* window);
-        delegate void NativeMenuItemSelectedDelegate(void* window, void* menu);        
+        delegate void NativeMenuItemSelectedDelegate(void* window, void* menu);
+		delegate void NativeDragDropFileDelegate(void* window, char8* filePath);
 
         public void* mNativeWindow;
 		public bool mNativeWindowClosed;
@@ -178,6 +180,7 @@ namespace Beefy
         static NativeMouseWheelDelegate sNativeMouseWheelDelegate ~ delete _;
         static NativeMouseLeaveDelegate sNativeMouseLeaveDelegate ~ delete _;
         static NativeMenuItemSelectedDelegate sNativeMenuItemSelectedDelegate ~ delete _;
+        static NativeDragDropFileDelegate sNativeDragDropFileDelegate ~ delete _;
 
         [CallingConvention(.Stdcall), CLink]
         static extern void* BFApp_CreateWindow(void* parent, char8* title, int32 x, int32 y, int32 width, int32 height, int32 windowFlags);
@@ -190,7 +193,7 @@ namespace Beefy
             void* gotFocusDelegate, void* lostFocusDelegate,
 			void* keyCharDelegate, void* keyDownDelegate, void* keyUpDelegate, void* hitTestDelegate,
             void* mouseMoveDelegate, void* mouseProxyMoveDelegate, void* mouseDownDelegate, void* mouseUpDelegate, void* mouseWheelDelegate, void* mouseLeaveDelegate,
-            void* menuItemSelectedDelegate);
+            void* menuItemSelectedDelegate, void* dragDropFileDelegate);
 
 		[CallingConvention(.Stdcall), CLink]
 		static extern void BFWindow_SetTitle(void* window, char8* title);
@@ -299,6 +302,7 @@ namespace Beefy
 		static void Static_NativeMouseWheelDelegate(void* window, int32 mouseX, int32 mouseY, float deltaX, float deltaY) { GetBFWindow(window).MouseWheel(mouseX, mouseY, deltaX, deltaY); }
 		static void Static_NativeMouseLeaveDelegate(void* window) { GetBFWindow(window).MouseLeave(); }
 		static void Static_NativeMenuItemSelectedDelegate(void* window, void* item) { GetBFWindow(window).NativeMenuItemSelected(item); }
+		static void Static_NativeDragDropFileDelegate(void* window, char8* filePath) { GetBFWindow(window).DragDropFile(StringView(filePath)); }
 		#endif
 
 		public this()
@@ -351,12 +355,13 @@ namespace Beefy
 				sNativeMouseWheelDelegate = new => Static_NativeMouseWheelDelegate;
 				sNativeMouseLeaveDelegate = new => Static_NativeMouseLeaveDelegate;
 				sNativeMenuItemSelectedDelegate = new => Static_NativeMenuItemSelectedDelegate;
+				sNativeDragDropFileDelegate = new => Static_NativeDragDropFileDelegate;
             }
 
             BFWindow_SetCallbacks(mNativeWindow, sNativeMovedDelegate.GetFuncPtr(), sNativeCloseQueryDelegate.GetFuncPtr(), sNativeClosedDelegate.GetFuncPtr(), sNativeGotFocusDelegate.GetFuncPtr(), sNativeLostFocusDelegate.GetFuncPtr(),
                 sNativeKeyCharDelegate.GetFuncPtr(), sNativeKeyDownDelegate.GetFuncPtr(), sNativeKeyUpDelegate.GetFuncPtr(), sNativeHitTestDelegate.GetFuncPtr(),
                 sNativeMouseMoveDelegate.GetFuncPtr(), sNativeMouseProxyMoveDelegate.GetFuncPtr(), sNativeMouseDownDelegate.GetFuncPtr(), sNativeMouseUpDelegate.GetFuncPtr(), sNativeMouseWheelDelegate.GetFuncPtr(), sNativeMouseLeaveDelegate.GetFuncPtr(),
-                sNativeMenuItemSelectedDelegate.GetFuncPtr());            
+                sNativeMenuItemSelectedDelegate.GetFuncPtr(), sNativeDragDropFileDelegate.GetFuncPtr());            
             BFApp.sApp.mWindows.Add(this);
 
             mDefaultDrawLayer = new DrawLayer(this);
@@ -575,6 +580,10 @@ namespace Beefy
             MenuItemSelected(aSysMenu);                      
         }
 
+		public virtual void DragDropFile(StringView filePath)
+		{
+		}
+
         public virtual SysBitmap LoadSysBitmap(String path)
         {
             return null;

+ 8 - 0
BeefLibs/Beefy2D/src/widgets/WidgetWindow.bf

@@ -17,6 +17,7 @@ namespace Beefy.widgets
     public delegate void MouseWheelHandler(MouseEvent mouseEvent);    
     public delegate void KeyDownHandler(KeyDownEvent keyboardEvent);
 	//public delegate void CloseTemporaryHandler(WidgetWindow window);
+	public delegate void DragDropFileHandler(StringView filePath);
     
     public class WidgetWindow : BFWindow
     {
@@ -31,6 +32,7 @@ namespace Beefy.widgets
         public Event<MenuItemSelectedHandler> mOnMenuItemSelected ~ _.Dispose();
         public Event<KeyDownHandler> mOnWindowKeyDown ~ _.Dispose();
     	public Event<delegate HitTestResult(int32, int32)> mOnHitTest ~ _.Dispose();
+		public Event<DragDropFileHandler> mOnDragDropFile ~ _.Dispose();
 
         public static Event<MouseLeftWindowHandler> sOnMouseLeftWindow ~ _.Dispose();
         public static Event<WindowLostFocusHandler> sOnWindowLostFocus ~ _.Dispose();
@@ -811,6 +813,12 @@ namespace Beefy.widgets
             sOnMenuItemSelected(sysMenu);
             base.MenuItemSelected(sysMenu);            
         }
+
+		public override void DragDropFile(StringView filePath)
+		{
+			mOnDragDropFile(filePath);
+			base.DragDropFile(filePath);
+		}
 		
 		public void TransferMouse(WidgetWindow newMouseWindow)
 		{

+ 2 - 1
BeefySysLib/BFWindow.cpp

@@ -153,7 +153,8 @@ BFWindow::BFWindow()
 	mMouseUpFunc = NULL;
 	mMouseWheelFunc = NULL;
 	mMouseLeaveFunc = NULL;
-	mMenuItemSelectedFunc = NULL;	
+	mMenuItemSelectedFunc = NULL;
+	mDragDropFileFunc = NULL;
 	mHitTestFunc = NULL;
 	mFlags = 0;
 

+ 6 - 3
BeefySysLib/BFWindow.h

@@ -23,6 +23,7 @@ typedef void (*BFWindow_MouseUp)(BFWindow* window, int x, int y, int btn);
 typedef void (*BFWindow_MouseWheel)(BFWindow* window, int x, int y, float deltaX, float deltaY);
 typedef void (*BFWindow_MouseLeave)(BFWindow* window);
 typedef void (*BFWindow_MenuItemSelectedFunc)(BFWindow* window, BFMenu* menu);
+typedef void (*BFWindow_DragDropFileFunc)(BFWindow* window, const char* filePath);
 
 enum
 {
@@ -53,7 +54,8 @@ enum
 	BFWINDOW_FAKEFOCUS		= 0x1000000,
 	BFWINDOW_SHOWMINIMIZED  = 0x2000000,
 	BFWINDOW_SHOWMAXIMIZED  = 0x4000000,
-	BFWINDOW_ALLOW_FULLSCREEN = 0x8000000
+	BFWINDOW_ALLOW_FULLSCREEN = 0x8000000,
+	BFWINDOW_ACCEPTFILES = 0x10000000
 	
 };
  
@@ -103,7 +105,7 @@ public:
 	uint32					mMouseDownTicks[MOUSEBUTTON_MAX];
 
 	BFMenu*					mMenu;
-	RenderWindow*			mRenderWindow;		
+	RenderWindow*			mRenderWindow;
 	bool					mNonExclusiveMouseCapture;
 	BFWindow_MovedFunc		mMovedFunc;
 	BFWindow_CloseQueryFunc mCloseQueryFunc;
@@ -120,7 +122,8 @@ public:
 	BFWindow_MouseUp		mMouseUpFunc;
 	BFWindow_MouseWheel		mMouseWheelFunc;
 	BFWindow_MouseLeave		mMouseLeaveFunc;
-	BFWindow_MenuItemSelectedFunc mMenuItemSelectedFunc;	
+	BFWindow_MenuItemSelectedFunc mMenuItemSelectedFunc;
+	BFWindow_DragDropFileFunc mDragDropFileFunc;
 	
 public:
 	BFWindow();

+ 3 - 2
BeefySysLib/BeefySysLib.cpp

@@ -283,7 +283,7 @@ BF_EXPORT void BF_CALLTYPE BFWindow_SetCallbacks(BFWindow* window, BFWindow_Move
 	BFWindow_KeyCharFunc keyCharFunc, BFWindow_KeyDownFunc keyDownFunc, BFWindow_KeyUpFunc keyUpFunc, BFWindow_HitTestFunc hitTestFunc,
 	BFWindow_MouseMove mouseMoveFunc, BFWindow_MouseProxyMove mouseProxyMoveFunc,
 	BFWindow_MouseDown mouseDownFunc, BFWindow_MouseUp mouseUpFunc, BFWindow_MouseWheel mouseWheelFunc, BFWindow_MouseLeave mouseLeaveFunc,
-	BFWindow_MenuItemSelectedFunc menuItemSelectedFunc)
+	BFWindow_MenuItemSelectedFunc menuItemSelectedFunc, BFWindow_DragDropFileFunc dragDropFileFunc)
 {
 	window->mMovedFunc = movedFunc;
 	window->mCloseQueryFunc = closeQueryFunc;
@@ -300,7 +300,8 @@ BF_EXPORT void BF_CALLTYPE BFWindow_SetCallbacks(BFWindow* window, BFWindow_Move
 	window->mMouseUpFunc = mouseUpFunc;
 	window->mMouseWheelFunc = mouseWheelFunc;
 	window->mMouseLeaveFunc = mouseLeaveFunc;
-	window->mMenuItemSelectedFunc = menuItemSelectedFunc;	
+	window->mMenuItemSelectedFunc = menuItemSelectedFunc;
+	window->mDragDropFileFunc = dragDropFileFunc;
 }
 
 BF_EXPORT void* BFWindow_GetNativeUnderlying(BFWindow* window)

+ 16 - 1
BeefySysLib/platform/win/WinBFApp.cpp

@@ -162,7 +162,10 @@ WinBFWindow::WinBFWindow(BFWindow* parent, const StringImpl& title, int x, int y
 	if (windowFlags & BFWINDOW_MAXIMIZE)
 		aWindowFlags |= WS_MAXIMIZEBOX;
 	if ((windowFlags & BFWINDOW_TOPMOST) && (parent == NULL))
-		windowFlagsEx |= WS_EX_TOPMOST;	
+		windowFlagsEx |= WS_EX_TOPMOST;
+	if ((windowFlags & BFWINDOW_ACCEPTFILES))
+		windowFlagsEx |= WS_EX_ACCEPTFILES;
+
 	if (windowFlags & BFWINDOW_CLIENT_SIZED)
 	{
 		RECT rect = {0, 0, width, height};
@@ -1123,6 +1126,18 @@ LRESULT WinBFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
 		case WM_INPUTLANGCHANGE:
 			mKeyLayoutHasAltGr = (KeyboardLayoutHasAltGr((HKL)lParam) == TRUE);
 			break;
+
+		case WM_DROPFILES:
+			{
+				HDROP hDropInfo = (HDROP)wParam;
+				char sItem[MAX_PATH];
+	
+				for(int i = 0; DragQueryFileA(hDropInfo, i, (LPSTR)sItem, sizeof(sItem)); i++)
+				    mDragDropFileFunc(this, sItem);
+
+				DragFinish(hDropInfo);
+			}
+			break;
 		}
 		
 		app->mInMsgProc = false;

+ 47 - 8
IDE/src/IDEApp.bf

@@ -846,6 +846,17 @@ namespace IDE
         public void DoOpenFile()
         {
 #if !CLI
+			if (mDeferredOpenFileName != null)
+			{
+				for (let filePath in mDeferredOpenFileName.Split('|'))
+				{
+					AddRecentFile(.OpenedFile, filePath);
+					ShowSourceFile(scope String()..Reference(filePath));
+				}
+				DeleteAndNullify!(mDeferredOpenFileName);
+				return;
+			}
+
 			String fullDir = scope .();
 			let sourceViewPanel = GetActiveSourceViewPanel();
 			if (sourceViewPanel != null)
@@ -7093,6 +7104,11 @@ namespace IDE
 
 		public override void UnhandledCommandLine(String key, String value)
 		{
+			if (File.Exists(key))
+			{
+				DragDropFile(key);
+				return;
+			}
 			Fail(StackStringFormat!("Unhandled command line param: {0}", key));
 		}
 
@@ -7238,13 +7254,7 @@ namespace IDE
 					else
 						mWorkspace.mDir = fullDir;
 				case "-file":
-					String.NewOrSet!(mDeferredOpenFileName, value);
-					if (mDeferredOpenFileName.EndsWith(".bfdbg", .OrdinalIgnoreCase))
-						mDeferredOpen = .DebugSession;
-					else if (mDeferredOpenFileName.EndsWith(".dmp", .OrdinalIgnoreCase))
-						mDeferredOpen = .CrashDump;
-					else
-						mDeferredOpen = .File;
+					DragDropFile(value);
 				default:
 					return false;
 				}
@@ -7252,6 +7262,34 @@ namespace IDE
 			}
         }
 
+		public void DragDropFile(StringView filePath)
+		{
+			let prevDeferredOpen = mDeferredOpen;
+
+			if (filePath.EndsWith(".bfdbg", .OrdinalIgnoreCase))
+				mDeferredOpen = .DebugSession;
+			else if (filePath.EndsWith(".dmp", .OrdinalIgnoreCase))
+				mDeferredOpen = .CrashDump;
+			else
+				mDeferredOpen = .File;
+
+			if (prevDeferredOpen == .File && mDeferredOpen == .File)
+			{
+				if (String.IsNullOrEmpty(mDeferredOpenFileName))
+					String.NewOrSet!(mDeferredOpenFileName, filePath);
+				else
+					mDeferredOpenFileName.AppendF("|{}", filePath);
+			}
+			else if (prevDeferredOpen != .None && prevDeferredOpen != .File && mDeferredOpen == .File)
+			{
+				// Do nothing
+			}
+			else
+			{
+				String.NewOrSet!(mDeferredOpenFileName, filePath);
+			}
+		}
+
         class Board : Widget
         {
             public override void Draw(Graphics g)
@@ -11498,7 +11536,7 @@ namespace IDE
 			//
 			{
 				BFWindow.Flags flags = .Border | .ThickFrame | .Resizable | .SysMenu |
-	                .Caption | .Minimize | .Maximize | .QuitOnClose | .Menu | .PopupPosition;
+	                .Caption | .Minimize | .Maximize | .QuitOnClose | .Menu | .PopupPosition | .AcceptFiles;
 				if (mRunningTestScript)
 					flags |= .NoActivate;
 
@@ -11528,6 +11566,7 @@ namespace IDE
 			mMainWindow.mOnMouseUp.Add(new => MouseUp);
             mMainWindow.mOnWindowKeyDown.Add(new => SysKeyDown);
             mMainWindow.mOnWindowCloseQuery.Add(new => AllowClose);
+			mMainWindow.mOnDragDropFile.Add(new => DragDropFile);
             CreateMenu();
             UpdateRecentDisplayedFilesMenuItems();
             if (mRecentlyDisplayedFiles.Count > 0)