added gaction2.nim example, and some small fixes

This commit is contained in:
Stefan Salewski 2019-12-05 19:11:11 +01:00
commit 68f99d33cb
7 changed files with 320 additions and 7 deletions

View file

@ -1,6 +1,6 @@
= High level GTK3 (and GTK4) bindings for the Nim programming language
(c) Stefan Salewski
//Version 0.6.0
//Version 0.6.1
:experimental:
:imagesdir: http://ssalewski.de/tmp
:source-highlighter: pygments
@ -1100,7 +1100,142 @@ main()
While in the previous example we create only a single menu instance in proc appStartup()
for all of our application windows, here we create a new menu for all of our instances
in proc appActivate(). That seems to work fine, so I assume it is correct.
in proc appActivate(). That seems to work fine, so I assume it is correct.
== GMenu and GAction with GTK Builder
And here is an example from https://github.com/GNOME/gtk/blob/mainline/tests/
which uses a combination of gaction and gmenu with a GTK builder XML file for
the menu description.
[[gaction2.nim]]
[source, nim]
.gaction2.nim
----
# nim c gaction2.nim
# https://github.com/GNOME/gtk/blob/mainline/tests/testgaction.c
# gcc -Wall gaction.c -o gaction `pkg-config --cflags --libs gtk4`
import gintro/[gtk, glib, gobject, gio]
const menuData = """
<interface>
<menu id="menuModel">
<section>
<item>
<attribute name="label">Normal Menu Item</attribute>
<attribute name="action">win.normal-menu-item</attribute>
</item>
<submenu>
<attribute name="label">Submenu</attribute>
<item>
<attribute name="label">Submenu Item</attribute>
<attribute name="action">win.submenu-item</attribute>
</item>
</submenu>
<item>
<attribute name="label">Toggle Menu Item</attribute>
<attribute name="action">win.toggle-menu-item</attribute>
</item>
</section>
<section>
<item>
<attribute name="label">Radio 1</attribute>
<attribute name="action">win.radio</attribute>
<attribute name="target">1</attribute>
</item>
<item>
<attribute name="label">Radio 2</attribute>
<attribute name="action">win.radio</attribute>
<attribute name="target">2</attribute>
</item>
<item>
<attribute name="label">Radio 3</attribute>
<attribute name="action">win.radio</attribute>
<attribute name="target">3</attribute>
</item>
</section>
</menu>
</interface>
"""
proc changeLabelButton(action: SimpleAction; v: Variant; label: Label) =
label.setLabel("Text set from button")
proc normalMenuItem(action: SimpleAction; v: Variant; label: Label) =
label.setLabel("Text set from normal menu item")
proc toggleMenuItem(action: SimpleAction; v: Variant; label: Label) =
label.setLabel("Text set from toggle menu item")
proc submenuItem(action: SimpleAction; v: Variant; label: Label) =
label.setLabel("Text set from submenu item")
proc radio(action: SimpleAction; parameter: Variant; label: Label) =
var l: uint64
let newState: Variant = newVariantString(getString(parameter, l))
let str: string = "From Radio menu item " & getString(newState, l)
label.setLabel(str)
proc bye(w: Window) =
mainQuit()
echo "Bye..."
proc main =
gtk.init()
let
window = newWindow()
box = newBox(Orientation.vertical, 12)
menubutton = newMenuButton()
button1 = newButton("Change Label Text")
label = newLabel("Initial Text")
actionGroup = newSimpleActionGroup()
window.connect("destroy", gtk.mainQuit)
#window.connect("destroy", bye)
var action = newSimpleAction("change-label-button")
discard action.connect("activate", changeLabelButton, label)
actionGroup.addAction(action)
action = newSimpleAction("normal-menu-item")
discard action.connect("activate", normalMenuItem, label)
actionGroup.addAction(action)
var v = newVariantBoolean(true)
action = newSimpleActionStateful("toggle-menu-item", nil, v)
discard action.connect("activate", toggleMenuItem, label)
actionGroup.addAction(action)
action = newSimpleAction("submenu-item")
discard action.connect("activate", subMenuItem, label)
actionGroup.addAction(action)
v = newVariantString("1")
let vt = newVariantType("s")
action = newSimpleActionStateful("radio", vt, v)
discard action.connect("activate", radio, label)
actionGroup.addAction(action)
insertActionGroup(window, "win", actionGroup)
label.setMarginTop(12)
label.setMarginBottom(12)
box.add(label)
menubutton.setHAlign(Align.center)
let builder: Builder = newBuilderFromString(menuData)
let menuModel = builder.getMenuModel("menuModel")
let menu = newMenuFromModel(menuModel)
menuButton.setPopup(menu)
box.add(menubutton)
button1.setHalign(Align.center)
button1.setActionName("win.change-label-button")
box.add(button1)
window.add(box)
window.showAll
gtk.main()
main()
----
== GSettings

View file

@ -23,3 +23,4 @@ proc main =
discard run(app)
main()

123
examples/gtk3/gaction2.nim Normal file
View file

@ -0,0 +1,123 @@
# nim c gaction.nim
# https://github.com/GNOME/gtk/blob/mainline/tests/testgaction.c
# gcc -Wall gaction.c -o gaction `pkg-config --cflags --libs gtk4`
import gintro/[gtk, glib, gobject, gio]
const menuData = """
<interface>
<menu id="menuModel">
<section>
<item>
<attribute name="label">Normal Menu Item</attribute>
<attribute name="action">win.normal-menu-item</attribute>
</item>
<submenu>
<attribute name="label">Submenu</attribute>
<item>
<attribute name="label">Submenu Item</attribute>
<attribute name="action">win.submenu-item</attribute>
</item>
</submenu>
<item>
<attribute name="label">Toggle Menu Item</attribute>
<attribute name="action">win.toggle-menu-item</attribute>
</item>
</section>
<section>
<item>
<attribute name="label">Radio 1</attribute>
<attribute name="action">win.radio</attribute>
<attribute name="target">1</attribute>
</item>
<item>
<attribute name="label">Radio 2</attribute>
<attribute name="action">win.radio</attribute>
<attribute name="target">2</attribute>
</item>
<item>
<attribute name="label">Radio 3</attribute>
<attribute name="action">win.radio</attribute>
<attribute name="target">3</attribute>
</item>
</section>
</menu>
</interface>
"""
proc changeLabelButton(action: SimpleAction; v: Variant; label: Label) =
label.setLabel("Text set from button")
proc normalMenuItem(action: SimpleAction; v: Variant; label: Label) =
label.setLabel("Text set from normal menu item")
proc toggleMenuItem(action: SimpleAction; v: Variant; label: Label) =
label.setLabel("Text set from toggle menu item")
proc submenuItem(action: SimpleAction; v: Variant; label: Label) =
label.setLabel("Text set from submenu item")
proc radio(action: SimpleAction; parameter: Variant; label: Label) =
var l: uint64
let newState: Variant = newVariantString(getString(parameter, l))
let str: string = "From Radio menu item " & getString(newState, l)
label.setLabel(str)
proc bye(w: Window) =
mainQuit()
echo "Bye..."
proc main =
gtk.init()
let
window = newWindow()
box = newBox(Orientation.vertical, 12)
menubutton = newMenuButton()
button1 = newButton("Change Label Text")
label = newLabel("Initial Text")
actionGroup = newSimpleActionGroup()
window.connect("destroy", gtk.mainQuit)
#window.connect("destroy", bye)
var action = newSimpleAction("change-label-button")
discard action.connect("activate", changeLabelButton, label)
actionGroup.addAction(action)
action = newSimpleAction("normal-menu-item")
discard action.connect("activate", normalMenuItem, label)
actionGroup.addAction(action)
var v = newVariantBoolean(true)
action = newSimpleActionStateful("toggle-menu-item", nil, v)
discard action.connect("activate", toggleMenuItem, label)
actionGroup.addAction(action)
action = newSimpleAction("submenu-item")
discard action.connect("activate", subMenuItem, label)
actionGroup.addAction(action)
v = newVariantString("1")
let vt = newVariantType("s")
action = newSimpleActionStateful("radio", vt, v)
discard action.connect("activate", radio, label)
actionGroup.addAction(action)
insertActionGroup(window, "win", actionGroup)
label.setMarginTop(12)
label.setMarginBottom(12)
box.add(label)
menubutton.setHAlign(Align.center)
let builder: Builder = newBuilderFromString(menuData)
let menuModel = builder.getMenuModel("menuModel")
let menu = newMenuFromModel(menuModel)
menuButton.setPopup(menu)
box.add(menubutton)
button1.setHalign(Align.center)
button1.setActionName("win.change-label-button")
box.add(button1)
window.add(box)
window.showAll
gtk.main()
main()

View file

@ -7,6 +7,7 @@ nim c count_button.nim
nim c darea_test.nim
nim c drawingarea.nim
nim c gaction.nim
nim c gaction2.nim
nim c gsettings.nim
nim c label.nim
nim c listview.nim
@ -19,3 +20,4 @@ nim c cairoImage.nim
nim c gstBasicTutorial1.nim
nim c sourceview_test.nim
nim c overlay_tree1.nim
nim c celldatafunction.nim

View file

@ -1,6 +1,6 @@
# Package
version = "0.6.0"
version = "0.6.1"
author = "Stefan Salewski"
description = "High level GObject-Introspection based GTK3/GTK4 bindings"
license = "MIT"

View file

@ -1,7 +1,7 @@
# This is the high level cairo module for Nim -- based on the low level ngtk3 module, manually tuned.
# (c) S. Salewski 2017, cairo 1.15.6
# v0.6.0
# 28-OCT-2019
# 03-DEC-2019
# starting with gintro v.0.6.0 we split cairo into the gobject-introspection generated cairo.nim and this file.
@ -242,6 +242,7 @@ proc cairo_pop_group*(cr: ptr Context00): ptr Pattern00 {.importc, libcairo.}
proc popGroup*(cr: Context): Pattern =
new(result, patternDestroy)
result.impl = cairo_pop_group(cr.impl)
GC_Ref(result)
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_pop_group_to_source*(cr: ptr Context00) {.importc, libcairo.}
@ -271,6 +272,11 @@ proc setSource*(cr: Context; red, green, blue: float) =
cairo_set_source_rgb(cr.impl, red.cdouble, green.cdouble, blue.cdouble)
#
#const `source=`* = setSourceRgb
proc setSource*(cr: Context; rgb: array[3, float]) =
cairo_set_source_rgb(cr.impl, rgb[0], rgb[1], rgb[2])
#
proc setSource*(cr: Context; rgb: tuple[r, g, b: float]) =
cairo_set_source_rgb(cr.impl, rgb[0], rgb[1], rgb[2])
proc cairo_set_source_rgba*(cr: ptr Context00; red, green, blue, alpha: cdouble) {.importc, libcairo.}
#
@ -279,6 +285,12 @@ proc setSource*(cr: Context; red, green, blue, alpha: float) =
cairo_set_source_rgba(cr.impl, red.cdouble, green.cdouble, blue.cdouble, alpha.cdouble)
#
#const `sourceRgba=`* = setSourceRgba
#
proc setSource*(cr: Context; rgba: array[4, float]) =
cairo_set_source_rgba(cr.impl, rgba[0], rgba[1], rgba[2], rgba[3])
#
proc setSource*(cr: Context; rgba: tuple[r, g, b, a: float]) =
cairo_set_source_rgba(cr.impl, rgba[0], rgba[1], rgba[2], rgba[3])
proc cairo_surface_get_reference_count*(surface: ptr Surface00): cuint {.importc, libcairo.}
#
@ -389,33 +401,53 @@ proc cairo_user_to_device*(cr: ptr Context00; x, y: var cdouble) {.importc, libc
#
proc userToDevice*(cr: Context; x, y: var float) =
var x1, y1: cdouble
(x1, y1) = (x, y)
cairo_user_to_device(cr.impl, x1, y1)
x = x1.float
y = y1.float
#
proc userToDevice*(cr: Context; x, y: float): array[2, float] =
result = [x, y]
cairo_user_to_device(cr.impl, result[0], result[1])
proc cairo_user_to_device_distance*(cr: ptr Context00; dx, dy: var cdouble) {.importc, libcairo.}
#
proc userToDeviceDistance*(cr: Context; dx, dy: var float) =
var dx1, dy1: cdouble
(dx1, dy1) = (dx, dy)
cairo_user_to_device_distance(cr.impl, dx1, dy1)
dx = dx1.float
dy = dy1.float
#
proc userToDeviceDistance*(cr: Context; dx, dy: float): array[2, float] =
result = [dx, dy]
cairo_user_to_device_distance(cr.impl, result[0], result[1])
proc cairo_device_to_user*(cr: ptr Context00; x, y: var cdouble) {.importc, libcairo.}
#
proc deviceToUser*(cr: Context; x, y: var float) =
var x1, y1: cdouble
(x1, y1) = (x, y)
cairo_device_to_user(cr.impl, x1, y1)
x = x1.float
y = y1.float
#
proc deviceToUser*(cr: Context; x, y: float): array[2, float] =
result = [x, y]
cairo_device_to_user(cr.impl, result[0], result[1])
proc cairo_device_to_user_distance*(cr: ptr Context00; dx, dy: var cdouble) {.importc, libcairo.}
#
proc deviceToUserDistance*(cr: Context; dx, dy: var float) =
var dx1, dy1: cdouble
(dx1, dy1) = (dx, dy)
cairo_device_to_user_distance(cr.impl, dx1, dy1)
dx = dx1.float
dy = dy1.float
#
proc deviceToUserDistance*(cr: Context; dx, dy: float): array[2, float] =
result = [dx, dy]
cairo_device_to_user_distance(cr.impl, result[0], result[1])
proc cairo_new_path*(cr: ptr Context00) {.importc, libcairo.}
#

View file

@ -1,5 +1,5 @@
# High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language
# v 0.6.0 2019-OCT-28
# v 0.6.1 2019-DEC-05
# (c) S. Salewski 2018
# https://wiki.gnome.org/Projects/GObjectIntrospection
@ -199,6 +199,7 @@ fixedProcNames.add("gst_element_factory_find", "findElementFactory")
defaultParameters.add("gtk_window_new", "`type` WindowType WindowType.toplevel")
defaultParameters.add("gtk_application_new", "flags gio.ApplicationFlags {}")
defaultParameters.add("gtk_builder_new_from_string", "length int64 -1")
for i in keywords: mangledNames.add(i, '`' & i & '`')
@ -1706,6 +1707,8 @@ const GTK_EPI = """
#proc loadFromData*(self: CssProvider; data: cstring): bool =
# loadFromData(self, uint8Array(data), -1)
proc mainQuit*(w: Window) = mainQuit()
proc gtk_file_chooser_dialog_new*(title: cstring; parent: ptr Window00; action: FileChooserAction;
firstButtonText: cstring = nil): ptr FileChooserDialog00 {.varargs,
importc: "gtk_file_chooser_dialog_new", libprag.}
@ -2036,6 +2039,18 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] =
assert false
else:
provInt[name] = interf
# Cross module interfaces -- maybe only a few, so we add it manually
# GSimpleActionGroup implements GActionGroup and GActionMap.
if namespace == "Gtk":
provInt["gio.SimpleActionGroup"] = @["gio.ActionGroup", "gio.ActionMap", "ActionGroup", "ActionMap"]
#provInt["gio.SimpleActionGroup"] = @["ActionGroup", "ActionMap"]
# The next two do not work, as gio does not import gtk! So we have to use converter proc.
# GtkApplication implements GActionGroup and GActionMap.
# provInt["Application"] = @["ActionGroup", "ActionMap"]
# GtkApplicationWindow implements AtkImplementorIface, GtkBuildable, GActionGroup and GActionMap.
# provInt["ApplicationWindow"] = @["ImplementorIface", "Buildable", "ActionGroup", "ActionMap"]
for obj, ifaces in provInt:
for i in ifaces:
if not interfaceProvider.contains(i):
@ -2187,7 +2202,11 @@ proc init* =
else:
output.write("include gisup4\n")
output.write("include gimpl\n")
buildableList.add("MenuModel")
for i in buildableList:
var prefix = "gtk"
if i == "MenuModel":
prefix = "g"
if i == "": continue
output.write(
"""
@ -2207,8 +2226,9 @@ proc get$1*(builder: Builder; name: string): $1 =
g_object_set_qdata(result.impl, Quark, addr(result[]))
assert(toBool(g_type_check_instance_is_a(cast[ptr TypeInstance00](result.impl), gt)))
""" % [i, "gtk_" & myCamelToSnake(i) & "_get_type()"])
""" % [i, prefix & "_" & myCamelToSnake(i) & "_get_type()"])
output.write("")
if namespace == "Gio":
output.write(GIO_EPI)
@ -2336,4 +2356,4 @@ proc launch() =
supmod4.close
launch()
# 2339 lines
# 2360 lines