Added open files dialog

This commit is contained in:
Kirurobo
2021-10-01 21:18:57 +09:00
parent 918563ce54
commit a2a03dd20d
7 changed files with 191 additions and 41 deletions

View File

@@ -32,6 +32,16 @@ namespace Kirurobo
ColorKey = 2,
}
/// <summary>
/// ダイアログの設定フラグ
/// </summary>
protected static class DialogFlag
{
public const uint ChooseFiles = 1;
public const uint ChooseDirectories = 2;
public const uint AllowMultipleSelection = 4;
}
#region Native functions
protected class LibUniWinC
{
@@ -111,6 +121,12 @@ namespace Kirurobo
[DllImport("LibUniWinC")]
public static extern bool UnregisterDropFilesCallback();
[DllImport("LibUniWinC")]
public static extern bool RegisterOpenFilesCallback([MarshalAs(UnmanagedType.FunctionPtr)] StringCallback callback);
[DllImport("LibUniWinC")]
public static extern bool UnregisterOpenFilesCallback();
[DllImport("LibUniWinC")]
public static extern bool RegisterMonitorChangedCallback([MarshalAs(UnmanagedType.FunctionPtr)] IntCallback callback);
@@ -148,12 +164,14 @@ namespace Kirurobo
public static extern void SetKeyColor(uint colorref);
[DllImport("LibUniWinC")]
public static extern void OpenFileDialog();
public static extern void OpenFileDialog(uint flags);
}
#endregion
static string[] lastDroppedFiles;
static string[] lastOpenedFiles;
static bool wasDropped = false;
static bool wasOpened = false;
static bool wasMonitorChanged = false;
static bool wasWindowStyleChanged = false;
@@ -240,6 +258,7 @@ namespace Kirurobo
// Instead of DetachWindow()
LibUniWinC.UnregisterDropFilesCallback();
LibUniWinC.UnregisterOpenFilesCallback();
LibUniWinC.UnregisterMonitorChangedCallback();
LibUniWinC.UnregisterWindowStyleChangedCallback();
}
@@ -276,7 +295,7 @@ namespace Kirurobo
/// </summary>
/// <param name="paths"></param>
[MonoPInvokeCallback(typeof(LibUniWinC.StringCallback))]
private static void _droppedFilesCallback([MarshalAs(UnmanagedType.LPWStr)] string paths)
private static void _dropFilesCallback([MarshalAs(UnmanagedType.LPWStr)] string paths)
{
// LF 区切りで届いた文字列を分割してパスの配列に直す
char[] delimiters = { '\n', '\r', '\t', '\0' };
@@ -290,9 +309,30 @@ namespace Kirurobo
wasDropped = true;
}
}
/// <summary>
/// ダイアログからファイル、フォルダが開かれた時に呼ばれるコールバック
/// 文字列を配列に直すことと、フラグを立てるまで行う
/// </summary>
/// <param name="paths"></param>
[MonoPInvokeCallback(typeof(LibUniWinC.StringCallback))]
private static void _openFilesCallback([MarshalAs(UnmanagedType.LPWStr)] string paths)
{
// LF 区切りで届いた文字列を分割してパスの配列に直す
char[] delimiters = { '\n', '\r', '\t', '\0' };
string[] files = paths.Split(delimiters).Where(s => s != "").ToArray();
if (files.Length > 0)
{
lastOpenedFiles = new string[files.Length];
files.CopyTo(lastOpenedFiles, 0);
wasOpened = true;
}
}
#endregion
#region Find, attach or detach
/// <summary>
@@ -326,7 +366,8 @@ namespace Kirurobo
LibUniWinC.AttachMyWindow();
#endif
// Add event handlers
LibUniWinC.RegisterDropFilesCallback(_droppedFilesCallback);
LibUniWinC.RegisterDropFilesCallback(_openFilesCallback);
LibUniWinC.RegisterOpenFilesCallback(_dropFilesCallback);
LibUniWinC.RegisterMonitorChangedCallback(_monitorChangedCallback);
LibUniWinC.RegisterWindowStyleChangedCallback(_windowStyleChangedCallback);
@@ -466,12 +507,25 @@ namespace Kirurobo
#endregion
#region About file dropping
#region File opening
public void SetAllowDrop(bool enabled)
{
LibUniWinC.SetAllowDrop(enabled);
}
/// <summary>
/// Open file selection dialog
/// </summary>
public void OpenFilesDialog()
{
uint flags = DialogFlag.AllowMultipleSelection | DialogFlag.ChooseFiles | DialogFlag.ChooseDirectories;
LibUniWinC.OpenFileDialog(flags);
}
#endregion
#region Event observers
/// <summary>
/// Check files dropping and unset the dropped flag
/// </summary>
@@ -487,6 +541,21 @@ namespace Kirurobo
return true;
}
/// <summary>
/// Check files opening and unset the opened flag
/// </summary>
/// <param name="files"></param>
/// <returns>true if files were dropped</returns>
public bool ObserveOpenedFiles(out string[] files)
{
files = lastOpenedFiles;
if (!wasOpened || files == null) return false;
wasOpened = false;
return true;
}
/// <summary>
/// Check the numbers of display or resolution changing, and unset the flag
/// </summary>

View File

@@ -276,11 +276,17 @@ namespace Kirurobo
public event OnStateChangedDelegate OnStateChanged;
public delegate void OnStateChangedDelegate();
public delegate void FilesDelegate(string[] files);
/// <summary>
/// Occurs after files or folders were dropped
/// </summary>
public event OnDropFilesDelegate OnDropFiles;
public delegate void OnDropFilesDelegate(string[] files);
public event FilesDelegate OnDropFiles;
/// <summary>
/// Occurs after files or folders were opened by dialog
/// </summary>
public event FilesDelegate OnOpenFiles;
/// <summary>
/// Occurs when the monitor settings or resolution changed
@@ -415,9 +421,14 @@ namespace Kirurobo
{
if (uniWinCore == null) return;
if (uniWinCore.ObserveDroppedFiles(out var files))
if (uniWinCore.ObserveDroppedFiles(out var droppedFiles))
{
OnDropFiles?.Invoke(files);
OnDropFiles?.Invoke(droppedFiles);
}
if (uniWinCore.ObserveOpenedFiles(out var openedFiles))
{
OnOpenFiles?.Invoke(openedFiles);
}
if (uniWinCore.ObserveMonitorChanged())
@@ -812,6 +823,13 @@ namespace Kirurobo
_allowDropFiles = enabled;
}
public void OpenFilesDialog() {
if (uniWinCore == null) return;
uniWinCore.OpenFilesDialog();
}
/// <summary>
/// 接続されているモニタ数を取得
/// </summary>

View File

@@ -117,6 +117,10 @@ namespace Kirurobo
{
ShowEventMessage(string.Join(Environment.NewLine, files));
};
uniwinc.OnOpenFiles += files =>
{
ShowEventMessage(string.Join(Environment.NewLine, files));
};
}
// UinWinCが準備できてなくても動くListener
@@ -206,6 +210,11 @@ namespace Kirurobo
}
}
if (Input.GetKeyUp(KeyCode.O))
{
uniwinc.OpenFilesDialog();
}
// Quit or stop playing when pressed [ESC]
if (Input.GetKey(KeyCode.Escape))
{

View File

@@ -290,7 +290,7 @@
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.8.1;
MARKETING_VERSION = 0.8.2;
PRODUCT_BUNDLE_IDENTIFIER = com.kirurobo.libuniwinc;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -318,7 +318,7 @@
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.8.1;
MARKETING_VERSION = 0.8.2;
PRODUCT_BUNDLE_IDENTIFIER = com.kirurobo.libuniwinc;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;

View File

@@ -140,6 +140,14 @@ UNIWINC_EXPORT BOOL UnregisterDropFilesCallback() {
return [LibUniWinC unregisterDropFilesCallback];
}
UNIWINC_EXPORT BOOL RegisterOpenFilesCallback(StringCallback callback) {
return [LibUniWinC registerOpenFilesCallbackWithCallback: callback];
}
UNIWINC_EXPORT BOOL UnregisterOpenFilesCallback() {
return [LibUniWinC unregisterOpenFilesCallback];
}
UNIWINC_EXPORT BOOL SetAllowDrop(BOOL enabled) {
return [LibUniWinC setAllowDropWithEnabled: enabled];
}
@@ -165,6 +173,6 @@ UNIWINC_EXPORT void Update() {
[LibUniWinC update];
}
UNIWINC_EXPORT void OpenFileDialog() {
[LibUniWinC openFileDialog];
UNIWINC_EXPORT void OpenFileDialog(UInt32 param) {
[LibUniWinC openFileDialogWithFlags: param];
}

View File

@@ -121,6 +121,7 @@ public class LibUniWinC : NSObject {
public typealias stringCallback = (@convention(c) (UnsafeRawPointer) -> Void)
public typealias intCallback = (@convention(c) (Int32) -> Void)
public static var dropFilesCallback: stringCallback? = nil
public static var openFilesCallback: stringCallback? = nil
public static var monitorChangedCallback: intCallback? = nil
public static var windowStyleChangedCallback: intCallback? = nil
private static var observerObject: Any? = nil
@@ -135,7 +136,8 @@ public class LibUniWinC : NSObject {
private static var monitorRectangles: [CGRect] = []
private static var monitorIndices: [Int] = []
private static let openFilePanel = NSOpenPanel()
// MARK: - Properties
///
@@ -321,7 +323,10 @@ public class LibUniWinC : NSObject {
overlayView?.removeFromSuperview()
overlayView = nil
}
// Close dialog if it is opened
openFilePanel.close()
targetWindow = nil
}
}
@@ -811,7 +816,17 @@ public class LibUniWinC : NSObject {
dropFilesCallback = nil
return true
}
@objc public static func registerOpenFilesCallback(callback: @escaping stringCallback) -> Bool {
openFilesCallback = callback
return true
}
@objc public static func unregisterOpenFilesCallback() -> Bool {
openFilesCallback = nil
return true
}
// MARK: - Mouser curosor
@@ -844,15 +859,62 @@ public class LibUniWinC : NSObject {
// MARK: - Open file dialog
@objc public static func openFileDialog() -> Void {
let dlg = NSOpenPanel()
dlg.allowsMultipleSelection = false
dlg.canChooseDirectories = false
dlg.canChooseFiles = true
dlg.level = NSWindow.Level.popUpMenu
/// Open dialog
/// - Parameters:
/// -
@objc public static func openFileDialog(flags: UInt32) -> Void {
openFilePanel.canChooseFiles = (flags & 0b0001 > 0)
openFilePanel.canChooseDirectories = (flags & 0b0010 > 0)
openFilePanel.allowsMultipleSelection = (flags & 0b0100 > 0)
openFilePanel.canCreateDirectories = false
openFilePanel.prompt = "Open"
openFilePanel.level = NSWindow.Level.popUpMenu
if (dlg.runModal() == NSApplication.ModalResponse.OK) {
openFilePanel.begin { (result) -> Void in
if (result == .OK) {
if (openFilePanel.urls.count > 0) {
// Make new-line separated string
var text: String = ""
for url in openFilePanel.urls {
text += url.path + "\n"
}
// Run callback
if (callStringCallback(callback: openFilesCallback, text: text)) {}
}
}
}
}
/// Call a StringCallback with UTF-16 paramete
/// - Parameters:
/// - callback: Registered callback function
/// - text: Parrameter as String
/// - Returns: True if success
public static func callStringCallback(callback: stringCallback?, text: String) -> Bool {
if (callback == nil)
{
return false
}
let count = text.utf16.count
if (count <= 0) {
return false
}
let buffer = UnsafeMutablePointer<uint16>.allocate(capacity: count + 1)
var i = 0
for c in text.utf16 {
buffer[i] = c
i += 1
}
buffer[count] = uint16.zero // End of the string
// Do callback
callback?(buffer)
buffer.deallocate()
return true
}
}

View File

@@ -93,26 +93,10 @@ class OverlayView: NSView {
}
// Make new-line separated string
let files: String = urls.componentsJoined(by: "¥n")
let count = files.utf16.count
if (count <= 0) {
return false
}
let buffer = UnsafeMutablePointer<uint16>.allocate(capacity: count + 1)
var i = 0
for c in files.utf16 {
buffer[i] = c
i += 1
}
buffer[count] = uint16.zero // End of the string
let files: String = urls.componentsJoined(by: "\n")
// Do callback
LibUniWinC.dropFilesCallback?(buffer)
buffer.deallocate()
return true
return LibUniWinC.callStringCallback(callback: LibUniWinC.dropFilesCallback, text: files)
}
override func draw(_ dirtyRect: NSRect) {