native_dialog.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. package al
  2. // Native dialogs extension
  3. /*
  4. #cgo pkg-config: allegro_dialog-5
  5. #cgo CFLAGS: -I/usr/local/include
  6. #cgo linux LDFLAGS: -lc_nonshared
  7. #include <stdlib.h>
  8. #include <stdint.h>
  9. #include <allegro5/allegro.h>
  10. #include <allegro5/allegro_native_dialog.h>
  11. #include "helpers.h"
  12. void al_append_native_text_log_wrapper(ALLEGRO_TEXTLOG * tl, const char * text) {
  13. al_append_native_text_log(tl, "%s", text);
  14. }
  15. */
  16. import "C"
  17. import "unsafe"
  18. import "runtime"
  19. const (
  20. FILECHOOSER_FILE_MUST_EXIST = 1
  21. FILECHOOSER_SAVE = 2
  22. FILECHOOSER_FOLDER = 4
  23. FILECHOOSER_PICTURES = 8
  24. FILECHOOSER_SHOW_HIDDEN = 16
  25. FILECHOOSER_MULTIPLE = 32
  26. MESSAGEBOX_WARN = 1 << 0
  27. MESSAGEBOX_ERROR = 1 << 1
  28. MESSAGEBOX_OK_CANCEL = 1 << 2
  29. MESSAGEBOX_YES_NO = 1 << 3
  30. MESSAGEBOX_QUESTION = 1 << 4
  31. TEXTLOG_NO_CLOSE = 1 << 0
  32. TEXTLOG_MONOSPACE = 1 << 1
  33. EVENT_NATIVE_DIALOG_CLOSE = 600
  34. EVENT_MENU_CLICK = 601
  35. MENU_ITEM_ENABLED = 0
  36. MENU_ITEM_CHECKBOX = 1
  37. MENU_ITEM_CHECKED = 2
  38. MENU_ITEM_DISABLED = 4
  39. )
  40. type FileChooser struct {
  41. handle *C.ALLEGRO_FILECHOOSER
  42. }
  43. // Converts a file chooser to it's underlying C pointer
  44. func (self *FileChooser) toC() *C.ALLEGRO_FILECHOOSER {
  45. return (*C.ALLEGRO_FILECHOOSER)(self.handle)
  46. }
  47. // Destroys the file chooser.
  48. func (self *FileChooser) Destroy() {
  49. if self.handle != nil {
  50. C.al_destroy_native_file_dialog(self.toC())
  51. }
  52. self.handle = nil
  53. }
  54. // Wraps a C file chooser into a go file chooser
  55. func wrapFileChooserRaw(data *C.ALLEGRO_FILECHOOSER) *FileChooser {
  56. if data == nil {
  57. return nil
  58. }
  59. return &FileChooser{data}
  60. }
  61. // Sets up a finalizer for this FileChooser that calls Destroy()
  62. func (self *FileChooser) SetDestroyFinalizer() *FileChooser {
  63. if self != nil {
  64. runtime.SetFinalizer(self, func(me *FileChooser) { me.Destroy() })
  65. }
  66. return self
  67. }
  68. // Wraps a C voice into a go mixer and sets up a finalizer that calls Destroy()
  69. func wrapFileChooser(data *C.ALLEGRO_FILECHOOSER) *FileChooser {
  70. self := wrapFileChooserRaw(data)
  71. return self.SetDestroyFinalizer()
  72. }
  73. type TextLog struct {
  74. handle *C.ALLEGRO_TEXTLOG
  75. }
  76. // Converts a native_text_log to it's underlying C pointer
  77. func (self *TextLog) toC() *C.ALLEGRO_TEXTLOG {
  78. return (*C.ALLEGRO_TEXTLOG)(self.handle)
  79. }
  80. // Closes the native_text_log.
  81. func (self *TextLog) Close() {
  82. if self.handle != nil {
  83. C.al_close_native_text_log(self.toC())
  84. }
  85. self.handle = nil
  86. }
  87. // Wraps a C native_text_log into a go native_text_log
  88. func wrapTextLogRaw(data *C.ALLEGRO_TEXTLOG) *TextLog {
  89. if data == nil {
  90. return nil
  91. }
  92. return &TextLog{data}
  93. }
  94. // Sets up a finalizer for this TextLog that calls Destroy()
  95. func (self *TextLog) SetDestroyFinalizer() *TextLog {
  96. if self != nil {
  97. runtime.SetFinalizer(self, func(me *TextLog) { me.Close() })
  98. }
  99. return self
  100. }
  101. // Wraps a C native_text_log into a go native_text_log and sets up a finalizer that calls Destroy()
  102. func wrapTextLog(data *C.ALLEGRO_TEXTLOG) *TextLog {
  103. self := wrapTextLogRaw(data)
  104. return self.SetDestroyFinalizer()
  105. }
  106. type Menu struct {
  107. handle *C.ALLEGRO_MENU
  108. }
  109. // Converts a menu to it's underlying C pointer
  110. func (self *Menu) toC() *C.ALLEGRO_MENU {
  111. return (*C.ALLEGRO_MENU)(self.handle)
  112. }
  113. // Destroys the menu.
  114. func (self *Menu) Destroy() {
  115. if self.handle != nil {
  116. C.al_destroy_menu(self.toC())
  117. }
  118. self.handle = nil
  119. }
  120. // Wraps a C menu into a go menu
  121. func wrapMenuRaw(data *C.ALLEGRO_MENU) *Menu {
  122. if data == nil {
  123. return nil
  124. }
  125. return &Menu{data}
  126. }
  127. // Sets up a finalizer for this Menu that calls Destroy()
  128. func (self *Menu) SetDestroyFinalizer() *Menu {
  129. if self != nil {
  130. runtime.SetFinalizer(self, func(me *Menu) { me.Destroy() })
  131. }
  132. return self
  133. }
  134. // Wraps a C menu into a go menu and sets up a finalizer that calls Destroy()
  135. func wrapMenu(data *C.ALLEGRO_MENU) *Menu {
  136. self := wrapMenuRaw(data)
  137. return self.SetDestroyFinalizer()
  138. }
  139. type MenuInfo C.ALLEGRO_MENU_INFO
  140. func makeMenuInfo(text *string, id, flags int, icon *Bitmap) C.ALLEGRO_MENU_INFO {
  141. res := C.ALLEGRO_MENU_INFO{}
  142. if text == nil {
  143. res.caption = nil
  144. } else {
  145. bytes := []byte(*text)
  146. res.caption = (*C.char)(unsafe.Pointer(&bytes[0]))
  147. }
  148. res.id = cui16(id)
  149. res.flags = ci(flags)
  150. res.icon = icon.handle
  151. return res
  152. }
  153. /// Formats a menuinfo element for an element of the menu.
  154. func MakeMenuInfo(text *string, id, flags int, icon *Bitmap) MenuInfo {
  155. return (MenuInfo)(makeMenuInfo(text, id, flags, icon))
  156. }
  157. // Returns a menuinfo that is a separator
  158. func MenuSeparator() MenuInfo {
  159. return MakeMenuInfo(nil, -1, 0, nil)
  160. }
  161. // Returns a menuinfo that is the start of the menu
  162. func StartOfMenu(caption string, id int) MenuInfo {
  163. return MakeMenuInfo(&caption, id, 0, nil)
  164. }
  165. // Returns a menuinfo that is the end of the menu
  166. func EndOfMenu(caption string, id int) MenuInfo {
  167. return MakeMenuInfo(nil, 0, 0, nil)
  168. }
  169. func (info * MenuInfo) toC() * C.ALLEGRO_MENU_INFO {
  170. return (*C.ALLEGRO_MENU_INFO)(info)
  171. }
  172. // Starts the native dialog addon
  173. func InitNativeDialogAddon() bool {
  174. return cb2b(C.al_init_native_dialog_addon())
  175. }
  176. // Stops the native dialog addon
  177. func ShutdownNativeDialogAddon() {
  178. C.al_shutdown_native_dialog_addon()
  179. }
  180. // Creates a native file dialog.
  181. func CreateNativeFileDialog(path, title, patterns string, mode int) *FileChooser {
  182. cpath := cstr(path) ; defer cstrFree(cpath)
  183. ctitle := cstr(title) ; defer cstrFree(ctitle)
  184. cpatterns:= cstr(patterns) ; defer cstrFree(cpatterns)
  185. return wrapFileChooser(C.al_create_native_file_dialog(cpath, ctitle, cpatterns, C.int(mode)))
  186. }
  187. func (dialog * FileChooser) Show(display * Display) bool {
  188. return bool(C.al_show_native_file_dialog(display.toC(), dialog.toC()))
  189. }
  190. func (display * Display) ShowNativeFileDialog(dialog * FileChooser) bool {
  191. return bool(C.al_show_native_file_dialog(display.toC(), dialog.toC()))
  192. }
  193. func (dialog * FileChooser) Count() int {
  194. return int(C.al_get_native_file_dialog_count(dialog.toC()))
  195. }
  196. func (dialog * FileChooser) Path(index int) string {
  197. return C.GoString(C.al_get_native_file_dialog_path(dialog.toC(), C.size_t(index)))
  198. }
  199. func (display * Display) ShowNativeMessageBox(title, heading, text, buttons string, flags int) int {
  200. ctitle := cstr(title) ; defer cstrFree(ctitle)
  201. cheading := cstr(heading) ; defer cstrFree(cheading)
  202. ctext := cstr(text) ; defer cstrFree(ctext)
  203. cbuttons := cstr(buttons) ; defer cstrFree(cbuttons)
  204. return int(C.al_show_native_message_box(display.toC(), ctitle, cheading, ctext, cbuttons, C.int(flags)))
  205. }
  206. // Creates a native text log.
  207. func CreateNativeTextLog(title string, flags int) * TextLog {
  208. ctitle := cstr(title) ; defer cstrFree(ctitle)
  209. return wrapTextLog(C.al_open_native_text_log(ctitle, C.int(flags)))
  210. }
  211. func (log * TextLog) Append(text string) {
  212. ctext := cstr(text) ; defer cstrFree(ctext)
  213. C.al_append_native_text_log_wrapper(log.toC(), ctext)
  214. }
  215. func (log * TextLog) EventSource() * EventSource {
  216. return wrapEventSourceRaw(C.al_get_native_text_log_event_source(log.toC()))
  217. }
  218. func CreateMenu() * Menu {
  219. return wrapMenu(C.al_create_menu())
  220. }
  221. func CreatePopupMenu() * Menu {
  222. return wrapMenu(C.al_create_popup_menu())
  223. }
  224. func BuildMenu(info * MenuInfo) * Menu {
  225. return wrapMenu(C.al_build_menu(info.toC()))
  226. }
  227. func (menu * Menu) AppendItem(title string, id, flags int, icon * Bitmap, submenu * Menu) int {
  228. ctitle := cstr(title) ; defer cstrFree(ctitle)
  229. return int(C.al_append_menu_item(menu.toC(), ctitle, C.uint16_t(id), C.int(flags), icon.toC(), submenu.toC()))
  230. }
  231. func (menu * Menu) InsertItem(pos int, title string, id, flags int, icon * Bitmap, submenu * Menu) int {
  232. ctitle := cstr(title) ; defer cstrFree(ctitle)
  233. return int(C.al_insert_menu_item(menu.toC(), C.int(pos), ctitle, C.uint16_t(id), C.int(flags), icon.toC(), submenu.toC()))
  234. }
  235. func (menu * Menu) RemoveItem(position int) bool {
  236. return bool(C.al_remove_menu_item(menu.toC(), C.int(position)))
  237. }
  238. func (menu * Menu) Clone() * Menu {
  239. return wrapMenu(C.al_clone_menu(menu.toC()))
  240. }
  241. func (menu * Menu) CloneForPopup() * Menu {
  242. return wrapMenu(C.al_clone_menu_for_popup(menu.toC()))
  243. }
  244. func (menu * Menu) Caption(pos int) string {
  245. return C.GoString(C.al_get_menu_item_caption(menu.toC(), C.int(pos)))
  246. }
  247. func (menu * Menu) SetCaption(pos int, caption string) {
  248. ccaption := cstr(caption) ; defer cstrFree(ccaption)
  249. C.al_set_menu_item_caption(menu.toC(), C.int(pos), ccaption)
  250. }
  251. func (menu * Menu) Flags(pos int) int {
  252. return int(C.al_get_menu_item_flags(menu.toC(), C.int(pos)))
  253. }
  254. func (menu * Menu) SetFlags(pos int, flags int) {
  255. C.al_set_menu_item_flags(menu.toC(), C.int(pos), C.int(flags))
  256. }
  257. func (menu * Menu) Icon(pos int) * Bitmap {
  258. return wrapBitmapRaw(C.al_get_menu_item_icon(menu.toC(), C.int(pos)))
  259. }
  260. func (menu * Menu) SetIcon(pos int, icon * Bitmap) {
  261. C.al_set_menu_item_icon(menu.toC(), C.int(pos), icon.toC())
  262. }
  263. func (menu * Menu) Find(id int) * Menu {
  264. res := C.al_find_menu(menu.toC(), C.uint16_t(id))
  265. return wrapMenuRaw(res)
  266. }
  267. func (menu * Menu) FindItem(id int) (ok bool, found * Menu, index int) {
  268. var cmenu * C.ALLEGRO_MENU = nil
  269. var cindex C.int = -1
  270. res := C.al_find_menu_item(menu.toC(), C.uint16_t(id), &cmenu, &cindex)
  271. ok = bool(res)
  272. found = wrapMenuRaw(cmenu)
  273. index = int(cindex)
  274. return ok, menu, index
  275. }
  276. func DefaultMenuEventSource() * EventSource {
  277. return wrapEventSourceRaw(C.al_get_default_menu_event_source())
  278. }
  279. func (menu * Menu) EnableEventSource() * EventSource {
  280. return wrapEventSourceRaw(C.al_enable_menu_event_source(menu.toC()))
  281. }
  282. func (menu * Menu) DisableEventSource() {
  283. C.al_disable_menu_event_source(menu.toC())
  284. }
  285. func (disp * Display) Menu() * Menu {
  286. return wrapMenuRaw(C.al_get_display_menu(disp.toC()))
  287. }
  288. func (disp * Display) SetMenu(menu * Menu) bool {
  289. return bool(C.al_set_display_menu(disp.toC(), menu.toC()))
  290. }
  291. func (disp * Display) PopupMenu(menu * Menu) bool {
  292. return bool(C.al_popup_menu(menu.toC(), disp.toC()))
  293. }
  294. func (menu * Menu) Popup(disp * Display) bool {
  295. return bool(C.al_popup_menu(menu.toC(), disp.toC()))
  296. }
  297. func (disp * Display) RemoveMenu() * Menu {
  298. return wrapMenuRaw(C.al_remove_display_menu(disp.toC()))
  299. }
  300. func NativeDialogVersion() uint32 {
  301. return uint32(C.al_get_allegro_native_dialog_version())
  302. }