GTK4 headerbar example added.
This commit is contained in:
parent
68f99d33cb
commit
e64c67bcb6
2 changed files with 261 additions and 0 deletions
143
README.adoc
143
README.adoc
|
|
@ -2617,5 +2617,148 @@ proc main =
|
|||
main()
|
||||
----
|
||||
|
||||
== A HeaderBar example for GTK4
|
||||
|
||||
The following code is the Nim version of a GTK4 example in C. It will work in its unmodified form
|
||||
only if you have GTK4 already installed -- my GTK4 lives at /opt/gtk and I have to type these
|
||||
commands before I can use GTK4 programs like gtk4-demo:
|
||||
|
||||
----
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/gtk/lib64/
|
||||
export GSETTINGS_SCHEMA_DIR=/opt/gtk/share/glib-2.0/schemas /opt/gtk/bin/gtk4-demo
|
||||
#export PKG_CONFIG_PATH="/opt/gtk/lib64/pkgconfig/" # only when compiling C code directly
|
||||
|
||||
----
|
||||
|
||||
The example is a bit complicated, as a custom (fake) headerbar is created, which involves a cast in C and Nim code.
|
||||
The example shows how to use a default headerbar, how to open a file dialog and how to use images and CSS styling.
|
||||
I guess most of the code would work in GTK3 also, but I have not tried to make a GTK3 version out of it, and I even
|
||||
do not understand all of the code yet. Note that for this example destroy() is not connected to the window close
|
||||
button, but called after gtk4.main(). A bit strange indeed, see forum note of Mr E.Bassi.
|
||||
|
||||
[[headerbar.nim]]
|
||||
[source,nim]
|
||||
.headerbar.nim
|
||||
----
|
||||
# https://github.com/GNOME/gtk/blob/mainline/tests/testheaderbar.c
|
||||
# nim c headerbar.nim
|
||||
import gintro/[gtk4, glib, gobject, gio]
|
||||
|
||||
const
|
||||
Css = """
|
||||
.main.background {
|
||||
background-image: linear-gradient(to bottom, red, blue);
|
||||
border-width: 0px;
|
||||
}
|
||||
.titlebar.backdrop {
|
||||
background-image: none;
|
||||
background-color: @bg_color;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
}
|
||||
.titlebar {
|
||||
background-image: linear-gradient(to bottom, white, @bg_color);
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
}
|
||||
"""
|
||||
|
||||
# we try to avoid use of global header variable as done in C code
|
||||
type
|
||||
MyWindow = ref object of gtk4.Window
|
||||
header: gtk4.Headerbar
|
||||
|
||||
proc response(d: gtk4.FileChooserDialog; responseID: int) = gtk4.destroy(d)
|
||||
|
||||
proc onBookmarkClicked(button: Button; data: MyWindow) =
|
||||
let window = gtk4.Window(data)
|
||||
let chooser = newFileChooserDialog("File Chooser Test", window,
|
||||
FileChooserAction.open)
|
||||
discard chooser.addButton("_Close", gtk4.ResponseType.close.ord)
|
||||
chooser.connect("response", response)
|
||||
chooser.show
|
||||
|
||||
proc changeSubtitle(button: Button; w: MyWindow) =
|
||||
if w.header.subtitle == "":
|
||||
w.header.setSubtitle("(subtle subtitle)")
|
||||
else:
|
||||
w.header.setSubtitle("") # can we pass nil?
|
||||
|
||||
proc toggleFullscreen(button: Button; window: MyWindow) =
|
||||
var fullscreen {.global.}: bool
|
||||
if fullscreen:
|
||||
window.unfullscreen
|
||||
fullscreen = false
|
||||
else:
|
||||
window.fullscreen
|
||||
fullscreen = true
|
||||
|
||||
proc toIntVal(i: int): Value =
|
||||
let gtype = typeFromName("gint")
|
||||
discard init(result, gtype)
|
||||
setInt(result, i)
|
||||
|
||||
proc quit(b: Button) = gtk4.mainQuit()
|
||||
|
||||
proc changeHeader(button: ToggleButton; window: MyWindow) =
|
||||
if button != nil and button.getActive:
|
||||
window.header = cast[HeaderBar](newBox(gtk4.Orientation.horizontal,
|
||||
10)) # intended cast, see C code!
|
||||
addClass(getStyleContext(window.header), "titlebar")
|
||||
addClass(getStyleContext(window.header), "header-bar")
|
||||
window.header.setProperty("margin", toIntVal(10))
|
||||
let label = newLabel("Label")
|
||||
window.header.add(label)
|
||||
let levelBar = newLevelBar()
|
||||
levelBar.setValue(0.4)
|
||||
levelBar.setHexpand
|
||||
window.header.add(levelBar)
|
||||
else:
|
||||
window.header = newHeaderBar()
|
||||
addClass(getStyleContext(window.header), "titlebar")
|
||||
window.header.setTitle("Example header")
|
||||
var button = newButton("_Close")
|
||||
button.setUseUnderline
|
||||
addClass(getStyleContext(button), "suggested-action")
|
||||
button.connect("clicked", quit)
|
||||
window.header.packEnd(button)
|
||||
button = newButton()
|
||||
let image = newImageFromIconName("bookmark-new-symbolic")
|
||||
button.connect("clicked", onBookmarkClicked, window)
|
||||
button.add(image)
|
||||
window.header.packStart(button)
|
||||
window.setTitlebar(window.header)
|
||||
|
||||
proc main =
|
||||
gtk4.init()
|
||||
var window: MyWindow
|
||||
initWindow(window)
|
||||
addClass(getStyleContext(window), "main")
|
||||
let provider = newCssProvider()
|
||||
provider.loadFromData(Css)
|
||||
addProviderForDisplay(getDisplay(window), provider, STYLE_PROVIDER_PRIORITY_USER)
|
||||
changeHeader(nil, window)
|
||||
let box = newBox(Orientation.vertical, 0)
|
||||
window.add(box)
|
||||
let content = newImageFromIconName("start-here-symbolic")
|
||||
content.setPixelSize(512)
|
||||
box.add(content)
|
||||
let footer = newActionBar()
|
||||
footer.setCenterWidget(newCheckButtonWithLabel("Middle"))
|
||||
let button = newToggleButtonWithLabel("Custom")
|
||||
button.connect("clicked", changeHeader, window)
|
||||
footer.packStart(button)
|
||||
var button1 = newButton("Subtitle")
|
||||
button1.connect("clicked", changeSubtitle, window)
|
||||
footer.packEnd(button1)
|
||||
button1 = newButton("Fullscreen")
|
||||
footer.packEnd(button1)
|
||||
button1.connect("clicked", toggleFullscreen, window)
|
||||
box.add(footer)
|
||||
window.show
|
||||
gtk4.main()
|
||||
destroy(window) # this is special for this example, see https://discourse.gnome.org/t/tests-testgaction-c/2232/6
|
||||
|
||||
main() # 118 lines
|
||||
----
|
||||
|
||||
NOTE: Related work: https://github.com/jdmansour/nim-smartgi
|
||||
|
||||
|
|
|
|||
118
examples/gtk4/headerbar.nim
Normal file
118
examples/gtk4/headerbar.nim
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
# https://github.com/GNOME/gtk/blob/mainline/tests/testheaderbar.c
|
||||
# nim c headerbar.nim
|
||||
import gintro/[gtk4, glib, gobject, gio]
|
||||
|
||||
const
|
||||
Css = """
|
||||
.main.background {
|
||||
background-image: linear-gradient(to bottom, red, blue);
|
||||
border-width: 0px;
|
||||
}
|
||||
.titlebar.backdrop {
|
||||
background-image: none;
|
||||
background-color: @bg_color;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
}
|
||||
.titlebar {
|
||||
background-image: linear-gradient(to bottom, white, @bg_color);
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
}
|
||||
"""
|
||||
|
||||
# we try to avoid use of global header variable as done in C code
|
||||
type
|
||||
MyWindow = ref object of gtk4.Window
|
||||
header: gtk4.Headerbar
|
||||
|
||||
proc response(d: gtk4.FileChooserDialog; responseID: int) = gtk4.destroy(d)
|
||||
|
||||
proc onBookmarkClicked(button: Button; data: MyWindow) =
|
||||
let window = gtk4.Window(data)
|
||||
let chooser = newFileChooserDialog("File Chooser Test", window,
|
||||
FileChooserAction.open)
|
||||
discard chooser.addButton("_Close", gtk4.ResponseType.close.ord)
|
||||
chooser.connect("response", response)
|
||||
chooser.show
|
||||
|
||||
proc changeSubtitle(button: Button; w: MyWindow) =
|
||||
if w.header.subtitle == "":
|
||||
w.header.setSubtitle("(subtle subtitle)")
|
||||
else:
|
||||
w.header.setSubtitle("") # can we pass nil?
|
||||
|
||||
proc toggleFullscreen(button: Button; window: MyWindow) =
|
||||
var fullscreen {.global.}: bool
|
||||
if fullscreen:
|
||||
window.unfullscreen
|
||||
fullscreen = false
|
||||
else:
|
||||
window.fullscreen
|
||||
fullscreen = true
|
||||
|
||||
proc toIntVal(i: int): Value =
|
||||
let gtype = typeFromName("gint")
|
||||
discard init(result, gtype)
|
||||
setInt(result, i)
|
||||
|
||||
proc quit(b: Button) = gtk4.mainQuit()
|
||||
|
||||
proc changeHeader(button: ToggleButton; window: MyWindow) =
|
||||
if button != nil and button.getActive:
|
||||
window.header = cast[HeaderBar](newBox(gtk4.Orientation.horizontal,
|
||||
10)) # intended cast, see C code!
|
||||
addClass(getStyleContext(window.header), "titlebar")
|
||||
addClass(getStyleContext(window.header), "header-bar")
|
||||
window.header.setProperty("margin", toIntVal(10))
|
||||
let label = newLabel("Label")
|
||||
window.header.add(label)
|
||||
let levelBar = newLevelBar()
|
||||
levelBar.setValue(0.4)
|
||||
levelBar.setHexpand
|
||||
window.header.add(levelBar)
|
||||
else:
|
||||
window.header = newHeaderBar()
|
||||
addClass(getStyleContext(window.header), "titlebar")
|
||||
window.header.setTitle("Example header")
|
||||
var button = newButton("_Close")
|
||||
button.setUseUnderline
|
||||
addClass(getStyleContext(button), "suggested-action")
|
||||
button.connect("clicked", quit)
|
||||
window.header.packEnd(button)
|
||||
button = newButton()
|
||||
let image = newImageFromIconName("bookmark-new-symbolic")
|
||||
button.connect("clicked", onBookmarkClicked, window)
|
||||
button.add(image)
|
||||
window.header.packStart(button)
|
||||
window.setTitlebar(window.header)
|
||||
|
||||
proc main =
|
||||
gtk4.init()
|
||||
var window: MyWindow
|
||||
initWindow(window)
|
||||
addClass(getStyleContext(window), "main")
|
||||
let provider = newCssProvider()
|
||||
provider.loadFromData(Css)
|
||||
addProviderForDisplay(getDisplay(window), provider, STYLE_PROVIDER_PRIORITY_USER)
|
||||
changeHeader(nil, window)
|
||||
let box = newBox(Orientation.vertical, 0)
|
||||
window.add(box)
|
||||
let content = newImageFromIconName("start-here-symbolic")
|
||||
content.setPixelSize(512)
|
||||
box.add(content)
|
||||
let footer = newActionBar()
|
||||
footer.setCenterWidget(newCheckButtonWithLabel("Middle"))
|
||||
let button = newToggleButtonWithLabel("Custom")
|
||||
button.connect("clicked", changeHeader, window)
|
||||
footer.packStart(button)
|
||||
var button1 = newButton("Subtitle")
|
||||
button1.connect("clicked", changeSubtitle, window)
|
||||
footer.packEnd(button1)
|
||||
button1 = newButton("Fullscreen")
|
||||
footer.packEnd(button1)
|
||||
button1.connect("clicked", toggleFullscreen, window)
|
||||
box.add(footer)
|
||||
window.show
|
||||
gtk4.main()
|
||||
destroy(window) # this is special for this example, see https://discourse.gnome.org/t/tests-testgaction-c/2232/6
|
||||
|
||||
main() # 118 lines
|
||||
Loading…
Add table
Add a link
Reference in a new issue