From 6db167297387d23301b5cca3299fc2acdfdee70f Mon Sep 17 00:00:00 2001 From: Jared Wahlstrand Date: Sat, 28 Sep 2024 12:08:47 -0400 Subject: [PATCH] add to dialog documentation --- docs/src/manual/dialogs.md | 53 +++++++++++++++++++++++++++++++++++++- src/windows.jl | 9 ++++--- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/docs/src/manual/dialogs.md b/docs/src/manual/dialogs.md index 603fe612..7d40d222 100644 --- a/docs/src/manual/dialogs.md +++ b/docs/src/manual/dialogs.md @@ -98,7 +98,7 @@ if isdir(dir[]) end ``` -### Filters +### File Filters Filters can be used to limit the type of files that the user can pick. Filters can be specified as a Tuple or Vector. A filter can be specified as a string, in which case it specifies a globbing pattern, for example `"*.png"`. You can specify multiple match types for a single filter by separating the patterns with a comma, for example `"*.png,*.jpg"`. @@ -108,3 +108,54 @@ The generic specification of a filter is GtkFileFilter(pattern = "", mimetype = "") ``` A human-readable name can optionally be provided using a keyword argument. + +## Custom dialogs + +You can define your own type of dialog by creating a window that closes and calls a function when a button is pressed. +For example: +```julia +using Gtk4 + +function callback_and_destroy(dlg, callback, args...) # calls the callback and destroys the dialog + callback(args...) + Gtk4.transient_for(dlg, nothing) + destroy(dlg) +end + +function custom_dialog(callback::Function, message::AbstractString, parent::GtkWindow) + dlg = GtkWindow(; modal = true) + box = GtkBox(:v) + push!(box, GtkLabel(message)) # or could put other widgets here + boxb = GtkBox(:h) # box with buttons for the bottom of the dialog + push!(box, boxb) + choice1 = GtkButton("Choice 1"; hexpand = true) + choice2 = GtkButton("Choice 2"; hexpand = true) + choice3 = GtkButton("Choice 3"; hexpand = true) + push!(boxb, choice1) + push!(boxb, choice2) + push!(boxb, choice3) + Gtk4.transient_for(dlg, parent) + dlg[] = box + + signal_connect(choice1, "clicked") do b + callback_and_destroy(dlg, callback, 1) + end + + signal_connect(choice2, "clicked") do b + callback_and_destroy(dlg, callback, 2) + end + + signal_connect(choice3, "clicked") do b + callback_and_destroy(dlg, callback, 3) + end + + show(dlg) + + return dlg +end + +custom_dialog("choice", GtkWindow("parent")) do val + println("Your choice was $val") +end +``` + diff --git a/src/windows.jl b/src/windows.jl index 891ea4a8..2d0ac043 100644 --- a/src/windows.jl +++ b/src/windows.jl @@ -307,12 +307,13 @@ window by default. Keyword arguments: - `timeout = -1` to set a time in seconds after which the dialog will close and `false` will be returned. Disabled if negative. +- `modal = true` sets whether the dialog is modal (i.e. stays on top of its parent window) """ -function input_dialog(message::AbstractString, entry_default::AbstractString, parent = nothing; timeout = -1) +function input_dialog(message::AbstractString, entry_default::AbstractString, parent = nothing; timeout = -1, modal = true) res = Ref{String}("") c = Condition() - input_dialog(message, entry_default, parent; timeout) do res_ + input_dialog(message, entry_default, parent; timeout, modal) do res_ res[] = res_ notify(c) end @@ -327,7 +328,7 @@ function _callback_and_destroy(dlg, callback, txt) end function input_dialog(callback::Function, message::AbstractString, entry_default::AbstractString, - parent = nothing; timeout = -1) + parent = nothing; timeout = -1, modal = true) dlg = GtkWindow() box = GtkBox(:v) push!(box, GtkLabel(message)) @@ -341,7 +342,7 @@ function input_dialog(callback::Function, message::AbstractString, entry_default cancel = GtkButton("Cancel"; hexpand = true) push!(boxb, cancel) push!(boxb, accept) - isnothing(parent) || (G_.set_transient_for(dlg, parent); G_.set_modal(dlg, true)) + isnothing(parent) || (G_.set_transient_for(dlg, parent); G_.set_modal(dlg, modal)) dlg[] = box signal_connect(cancel, "clicked") do b