144 lines
4.2 KiB
Odin
144 lines
4.2 KiB
Odin
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
|
|
}
|