mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 17:34:43 +00:00
227 lines
7.3 KiB
Nim
Executable File
227 lines
7.3 KiB
Nim
Executable File
#
|
|
#
|
|
# Nimrod's Runtime Library
|
|
# (c) Copyright 2012 Andreas Rumpf
|
|
#
|
|
# See the file "copying.txt", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
|
|
## This module implements portable dialogs for Nimrod; the implementation
|
|
## builds on the GTK interface. On Windows, native dialogs are shown instead.
|
|
|
|
import
|
|
glib2, gtk2
|
|
|
|
when defined(Windows):
|
|
import windows, ShellAPI, os
|
|
|
|
proc info*(window: PWindow, msg: string) =
|
|
## Shows an information message to the user. The process waits until the
|
|
## user presses the OK button.
|
|
when defined(Windows):
|
|
discard MessageBoxA(0, msg, "Information", MB_OK or MB_ICONINFORMATION)
|
|
else:
|
|
var dialog = message_dialog_new(window,
|
|
DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT,
|
|
MESSAGE_INFO, BUTTONS_OK, "%s", cstring(msg))
|
|
setTitle(dialog, "Information")
|
|
discard run(dialog)
|
|
destroy(PWidget(dialog))
|
|
|
|
proc warning*(window: PWindow, msg: string) =
|
|
## Shows a warning message to the user. The process waits until the user
|
|
## presses the OK button.
|
|
when defined(Windows):
|
|
discard MessageBoxA(0, msg, "Warning", MB_OK or MB_ICONWARNING)
|
|
else:
|
|
var dialog = DIALOG(message_dialog_new(window,
|
|
DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT,
|
|
MESSAGE_WARNING, BUTTONS_OK, "%s", cstring(msg)))
|
|
setTitle(dialog, "Warning")
|
|
discard run(dialog)
|
|
destroy(PWidget(dialog))
|
|
|
|
proc error*(window: PWindow, msg: string) =
|
|
## Shows an error message to the user. The process waits until the user
|
|
## presses the OK button.
|
|
when defined(Windows):
|
|
discard MessageBoxA(0, msg, "Error", MB_OK or MB_ICONERROR)
|
|
else:
|
|
var dialog = DIALOG(message_dialog_new(window,
|
|
DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT,
|
|
MESSAGE_ERROR, BUTTONS_OK, "%s", cstring(msg)))
|
|
setTitle(dialog, "Error")
|
|
discard run(dialog)
|
|
destroy(PWidget(dialog))
|
|
|
|
|
|
proc ChooseFileToOpen*(window: PWindow, root: string = ""): string =
|
|
## Opens a dialog that requests a filename from the user. Returns ""
|
|
## if the user closed the dialog without selecting a file. On Windows,
|
|
## the native dialog is used, else the GTK dialog is used.
|
|
when defined(Windows):
|
|
var
|
|
opf: TOPENFILENAME
|
|
buf: array [0..2047, char]
|
|
opf.lStructSize = sizeof(opf)
|
|
if root.len > 0:
|
|
opf.lpstrInitialDir = root
|
|
opf.lpstrFilter = "All Files\0*.*\0\0"
|
|
opf.flags = OFN_FILEMUSTEXIST
|
|
opf.lpstrFile = buf
|
|
opf.nMaxFile = sizeof(buf)
|
|
var res = GetOpenFileName(addr(opf))
|
|
if res != 0:
|
|
result = $buf
|
|
else:
|
|
result = ""
|
|
else:
|
|
var chooser = file_chooser_dialog_new("Open File", window,
|
|
FILE_CHOOSER_ACTION_OPEN,
|
|
STOCK_CANCEL, RESPONSE_CANCEL,
|
|
STOCK_OPEN, RESPONSE_OK, nil)
|
|
if root.len > 0:
|
|
discard set_current_folder(chooser, root)
|
|
if run(chooser) == cint(RESPONSE_OK):
|
|
var x = get_filename(chooser)
|
|
result = $x
|
|
g_free(x)
|
|
else:
|
|
result = ""
|
|
destroy(PWidget(chooser))
|
|
|
|
proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
|
|
## Opens a dialog that requests filenames from the user. Returns ``@[]``
|
|
## if the user closed the dialog without selecting a file. On Windows,
|
|
## the native dialog is used, else the GTK dialog is used.
|
|
when defined(Windows):
|
|
var
|
|
opf: TOPENFILENAME
|
|
buf: array [0..2047*4, char]
|
|
opf.lStructSize = sizeof(opf)
|
|
if root.len > 0:
|
|
opf.lpstrInitialDir = root
|
|
opf.lpstrFilter = "All Files\0*.*\0\0"
|
|
opf.flags = OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT or OFN_EXPLORER
|
|
opf.lpstrFile = buf
|
|
opf.nMaxFile = sizeof(buf)
|
|
var res = GetOpenFileName(addr(opf))
|
|
result = @[]
|
|
if res != 0:
|
|
# parsing the result is horrible:
|
|
var
|
|
i = 0
|
|
s: string
|
|
path = ""
|
|
while buf[i] != '\0':
|
|
add(path, buf[i])
|
|
inc(i)
|
|
inc(i)
|
|
if buf[i] != '\0':
|
|
while true:
|
|
s = ""
|
|
while buf[i] != '\0':
|
|
add(s, buf[i])
|
|
inc(i)
|
|
add(result, s)
|
|
inc(i)
|
|
if buf[i] == '\0': break
|
|
for i in 0..result.len-1: result[i] = os.joinPath(path, result[i])
|
|
else:
|
|
# only one file selected --> gosh, what an ungly thing
|
|
# the windows API is
|
|
add(result, path)
|
|
else:
|
|
var chooser = file_chooser_dialog_new("Open Files", window,
|
|
FILE_CHOOSER_ACTION_OPEN,
|
|
STOCK_CANCEL, RESPONSE_CANCEL,
|
|
STOCK_OPEN, RESPONSE_OK, nil)
|
|
if root.len > 0:
|
|
discard set_current_folder(chooser, root)
|
|
set_select_multiple(chooser, true)
|
|
result = @[]
|
|
if run(chooser) == cint(RESPONSE_OK):
|
|
var L = get_filenames(chooser)
|
|
var it = L
|
|
while it != nil:
|
|
add(result, $cast[cstring](it.data))
|
|
g_free(it.data)
|
|
it = it.next
|
|
free(L)
|
|
destroy(PWidget(chooser))
|
|
|
|
|
|
proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
|
|
## Opens a dialog that requests a filename to save to from the user.
|
|
## Returns "" if the user closed the dialog without selecting a file.
|
|
## On Windows, the native dialog is used, else the GTK dialog is used.
|
|
when defined(Windows):
|
|
var
|
|
opf: TOPENFILENAME
|
|
buf: array [0..2047, char]
|
|
opf.lStructSize = sizeof(opf)
|
|
if root.len > 0:
|
|
opf.lpstrInitialDir = root
|
|
opf.lpstrFilter = "All Files\0*.*\0\0"
|
|
opf.flags = OFN_OVERWRITEPROMPT
|
|
opf.lpstrFile = buf
|
|
opf.nMaxFile = sizeof(buf)
|
|
var res = GetSaveFileName(addr(opf))
|
|
if res != 0:
|
|
result = $buf
|
|
else:
|
|
result = ""
|
|
else:
|
|
var chooser = file_chooser_dialog_new("Save File", window,
|
|
FILE_CHOOSER_ACTION_SAVE,
|
|
STOCK_CANCEL, RESPONSE_CANCEL,
|
|
STOCK_SAVE, RESPONSE_OK, nil)
|
|
if root.len > 0:
|
|
discard set_current_folder(chooser, root)
|
|
set_do_overwrite_confirmation(chooser, true)
|
|
if run(chooser) == cint(RESPONSE_OK):
|
|
var x = get_filename(chooser)
|
|
result = $x
|
|
g_free(x)
|
|
else:
|
|
result = ""
|
|
destroy(PWidget(chooser))
|
|
|
|
|
|
proc ChooseDir*(window: PWindow, root: string = ""): string =
|
|
## Opens a dialog that requests a directory from the user.
|
|
## Returns "" if the user closed the dialog without selecting a directory.
|
|
## On Windows, the native dialog is used, else the GTK dialog is used.
|
|
when defined(Windows):
|
|
var
|
|
lpItemID: PItemIDList
|
|
BrowseInfo: TBrowseInfo
|
|
DisplayName: array [0..MAX_PATH, char]
|
|
TempPath: array [0..MAX_PATH, char]
|
|
Result = ""
|
|
#BrowseInfo.hwndOwner = Application.Handle
|
|
BrowseInfo.pszDisplayName = DisplayName
|
|
BrowseInfo.ulFlags = 1 #BIF_RETURNONLYFSDIRS
|
|
lpItemID = SHBrowseForFolder(cast[LPBrowseInfo](addr(BrowseInfo)))
|
|
if lpItemId != nil:
|
|
discard SHGetPathFromIDList(lpItemID, TempPath)
|
|
Result = $TempPath
|
|
discard GlobalFreePtr(lpItemID)
|
|
else:
|
|
var chooser = file_chooser_dialog_new("Select Directory", window,
|
|
FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
|
STOCK_CANCEL, RESPONSE_CANCEL,
|
|
STOCK_OPEN, RESPONSE_OK, nil)
|
|
if root.len > 0:
|
|
discard set_current_folder(chooser, root)
|
|
if run(chooser) == cint(RESPONSE_OK):
|
|
var x = get_filename(chooser)
|
|
result = $x
|
|
g_free(x)
|
|
else:
|
|
result = ""
|
|
destroy(PWidget(chooser))
|
|
|