package osdialog import "core:c" import "core:strings" // ─── Enums ──────────────────────────────────────────────────────── Message_Level :: enum c.int { INFO = 0, WARNING = 1, ERROR = 2, } Message_Buttons :: enum c.int { OK = 0, OK_CANCEL = 1, YES_NO = 2, } File_Action :: enum c.int { OPEN = 0, OPEN_DIR = 1, SAVE = 2, } Color :: struct { r, g, b, a: u8, } // ─── Filter Types ───────────────────────────────────────────────── Filter_Patterns :: struct { pattern: cstring, next: ^Filter_Patterns, } Filters :: struct { name: cstring, patterns: ^Filter_Patterns, next: ^Filters, } // ─── Foreign Imports ────────────────────────────────────────────── foreign import osdialog_lib "system:osdialog" foreign import libc "system:c" @(default_calling_convention = "c") foreign osdialog_lib { osdialog_message :: proc(level: Message_Level, buttons: Message_Buttons, message: cstring) -> c.int --- osdialog_prompt :: proc(level: Message_Level, message: cstring, text: cstring) -> cstring --- osdialog_file :: proc(action: File_Action, dir: cstring, filename: cstring, filters: ^Filters) -> cstring --- osdialog_filters_parse :: proc(str: cstring) -> ^Filters --- osdialog_filters_free :: proc(filters: ^Filters) --- osdialog_color_picker :: proc(color: ^Color, opacity: c.int) -> c.int --- osdialog_strdup :: proc(s: cstring) -> cstring --- osdialog_strndup :: proc(s: cstring, n: c.size_t) -> cstring --- } @(default_calling_convention = "c") foreign libc { free :: proc(ptr: rawptr) --- } // ─── Convenience Wrappers ───────────────────────────────────────── @(private) alloc_cstr :: proc(s: string) -> cstring { if len(s) == 0 { return nil } return strings.clone_to_cstring(s) } @(private) free_cstr :: proc(cs: cstring) { if cs != nil { delete(cs) } } open_file_dialog :: proc(default_dir: string = "", filters_str: string = "") -> string { dir_c := alloc_cstr(default_dir) defer free_cstr(dir_c) filter_c := alloc_cstr(filters_str) defer free_cstr(filter_c) filters: ^Filters if filter_c != nil { filters = osdialog_filters_parse(filter_c) defer osdialog_filters_free(filters) } result := osdialog_file(.OPEN, dir_c, nil, filters) if result == nil { return "" } defer free(rawptr(result)) return string(result) } save_file_dialog :: proc(default_dir: string = "", default_name: string = "", filters_str: string = "") -> string { dir_c := alloc_cstr(default_dir) defer free_cstr(dir_c) name_c := alloc_cstr(default_name) defer free_cstr(name_c) filter_c := alloc_cstr(filters_str) defer free_cstr(filter_c) filters: ^Filters if filter_c != nil { filters = osdialog_filters_parse(filter_c) defer osdialog_filters_free(filters) } result := osdialog_file(.SAVE, dir_c, name_c, filters) if result == nil { return "" } defer free(rawptr(result)) return string(result) } open_folder_dialog :: proc(default_dir: string = "") -> string { dir_c := alloc_cstr(default_dir) defer free_cstr(dir_c) result := osdialog_file(.OPEN_DIR, dir_c, nil, nil) if result == nil { return "" } defer free(rawptr(result)) return string(result) } show_message :: proc(level: Message_Level, buttons: Message_Buttons, message: string) -> bool { msg_c := alloc_cstr(message) defer free_cstr(msg_c) result := osdialog_message(level, buttons, msg_c) return result == 1 } show_prompt :: proc(level: Message_Level, message: string, default_text: string = "") -> string { msg_c := alloc_cstr(message) defer free_cstr(msg_c) text_c := alloc_cstr(default_text) defer free_cstr(text_c) result := osdialog_prompt(level, msg_c, text_c) if result == nil { return "" } defer free(rawptr(result)) return string(result) } pick_color :: proc(r, g, b: u8, a: u8 = 255) -> (Color, bool) { color := Color{r, g, b, a} ok := osdialog_color_picker(&color, 1) return color, ok == 1 }