new() with typedesc
This commit is contained in:
parent
67618a6119
commit
e20c95abf5
4 changed files with 44 additions and 24 deletions
29
README.adoc
29
README.adoc
|
|
@ -1,6 +1,6 @@
|
||||||
= High level GTK3 (and GTK4) bindings for the Nim programming language
|
= High level GTK3 (and GTK4) bindings for the Nim programming language
|
||||||
(c) Stefan Salewski
|
(c) Stefan Salewski
|
||||||
//Version 0.7.2
|
//Version 0.7.3
|
||||||
:experimental:
|
:experimental:
|
||||||
:imagesdir: http://ssalewski.de/tmp
|
:imagesdir: http://ssalewski.de/tmp
|
||||||
:source-highlighter: pygments
|
:source-highlighter: pygments
|
||||||
|
|
@ -25,8 +25,14 @@ with code inserted from files directly.
|
||||||
NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf, E. Bassi and other _Nim_ and _GTK/Gnome_ developers.
|
NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf, E. Bassi and other _Nim_ and _GTK/Gnome_ developers.
|
||||||
The `combinatorics` module was kindly provided by R. Behrends.
|
The `combinatorics` module was kindly provided by R. Behrends.
|
||||||
|
|
||||||
|
NOTE: Starting with current version v0.7.3 we allow passing a type descriptor as first parameter to the
|
||||||
|
new() procs like `newButton(MyButtonSubclass)` to support subclassing and extending Widgets in OOP style.
|
||||||
|
See <<Extending or sub-classing Widgets>> for an complete example. The init() procs which were used
|
||||||
|
before for this task are now deprecated and will be removed later. This new approach generally saves
|
||||||
|
one line of source code, allows using `let` instead of `var`, and the naming of procs is more consistent.
|
||||||
|
|
||||||
NOTE: Starting with version v0.7.1 we have added destructor support when compiled with `--gc:arc`,
|
NOTE: Starting with version v0.7.1 we have added destructor support when compiled with `--gc:arc`,
|
||||||
so we have no memory leak for subclassed objects any more, see the example in `Subclassing` section.
|
so we have no memory leak for subclassed objects any more, see the example in <<Extending or sub-classing Widgets>> section.
|
||||||
When compiled with default (refc) GC finalizers are used as before. And for objects marked with `nullable`
|
When compiled with default (refc) GC finalizers are used as before. And for objects marked with `nullable`
|
||||||
tag in gobject-introspection we now return nil value for the proxy object when the C lib has returned NULL.
|
tag in gobject-introspection we now return nil value for the proxy object when the C lib has returned NULL.
|
||||||
So according to the C API docs, you can check for nil result for the few functions which may return NULL.
|
So according to the C API docs, you can check for nil result for the few functions which may return NULL.
|
||||||
|
|
@ -597,13 +603,17 @@ Remember the GTK `devhelp` tool, and use also `grep` or the `nimgrep` variant.
|
||||||
|
|
||||||
== Extending or sub-classing Widgets
|
== Extending or sub-classing Widgets
|
||||||
|
|
||||||
I may occur that we want to attach additional information to GTK widgets
|
It may occur that we want to attach additional information to GTK widgets
|
||||||
by extending or subclassing them. Doing this is supported
|
by extending or subclassing them. [line-through]#Doing this is supported
|
||||||
by providing for each widget class not only a corresponding new() proc which returns
|
by providing for each widget class not only a corresponding new() proc which returns
|
||||||
the newly created widget, but also
|
the newly created widget, but also
|
||||||
a init() proc, which gets an uninitialized variable of the (extended) widget type as argument and
|
a init() proc, which gets an uninitialized variable of the (extended) widget type as argument and
|
||||||
initializes that variable with a newly created
|
initializes that variable with a newly created
|
||||||
GTK widget . Initializing the added fields is
|
GTK widget.#
|
||||||
|
Doing this is supported
|
||||||
|
by providing for each widget class an additional new() proc which takes an type descriptor
|
||||||
|
as first argument, like `newButton(CountButton, "Counting down from 100 by 5")` in the example below.
|
||||||
|
Initializing the added fields is
|
||||||
done separately by the user. The following code shows a GTK button, which is
|
done separately by the user. The following code shows a GTK button, which is
|
||||||
extended with a counter member field. That counter is decreased for
|
extended with a counter member field. That counter is decreased for
|
||||||
each button click. The amount of decrease (5) is passed to the callback as a int parameter.
|
each button click. The amount of decrease (5) is passed to the callback as a int parameter.
|
||||||
|
|
@ -621,13 +631,13 @@ to test the destructor behaviour.)
|
||||||
.count_button.nim
|
.count_button.nim
|
||||||
----
|
----
|
||||||
# nim c count_button.nim
|
# nim c count_button.nim
|
||||||
import gintro/[gtk, glib, gobject, gio]
|
import gintro/[gtk, gobject, gio]
|
||||||
|
|
||||||
type
|
type
|
||||||
CountButton = ref object of Button
|
CountButton = ref object of Button
|
||||||
counter: int
|
counter: int
|
||||||
|
|
||||||
when compileOption("gc", "arc"):
|
when defined(gcDestructors):
|
||||||
proc `=destroy`(x: var typeof(CountButton()[])) =
|
proc `=destroy`(x: var typeof(CountButton()[])) =
|
||||||
gtk.`=destroy`(typeof(Button()[])(x))
|
gtk.`=destroy`(typeof(Button()[])(x))
|
||||||
|
|
||||||
|
|
@ -637,10 +647,11 @@ proc buttonClicked (button: CountButton; decrement: int) =
|
||||||
echo "Counter is now: ", button.counter
|
echo "Counter is now: ", button.counter
|
||||||
|
|
||||||
proc appActivate (app: Application) =
|
proc appActivate (app: Application) =
|
||||||
var button: CountButton
|
#var button: CountButton
|
||||||
let window = newApplicationWindow(app)
|
let window = newApplicationWindow(app)
|
||||||
window.title = "Count Button"
|
window.title = "Count Button"
|
||||||
initButton(button, "Counting down from 100 by 5")
|
#initButton(button, "Counting down from 100 by 5") # deprecated
|
||||||
|
let button = newButton(CountButton, "Counting down from 100 by 5")
|
||||||
button.counter = 100
|
button.counter = 100
|
||||||
window.add(button)
|
window.add(button)
|
||||||
button.connect("clicked", buttonClicked, 5)
|
button.connect("clicked", buttonClicked, 5)
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
# nim c count_button.nim
|
# nim c count_button.nim
|
||||||
import gintro/[gtk, glib, gobject, gio]
|
import gintro/[gtk, gobject, gio]
|
||||||
|
|
||||||
type
|
type
|
||||||
CountButton = ref object of Button
|
CountButton = ref object of Button
|
||||||
counter: int
|
counter: int
|
||||||
|
|
||||||
when compileOption("gc", "arc"):
|
when defined(gcDestructors):
|
||||||
proc `=destroy`(x: var typeof(CountButton()[])) =
|
proc `=destroy`(x: var typeof(CountButton()[])) =
|
||||||
gtk.`=destroy`(typeof(Button()[])(x))
|
gtk.`=destroy`(typeof(Button()[])(x))
|
||||||
|
|
||||||
|
|
@ -15,10 +15,11 @@ proc buttonClicked (button: CountButton; decrement: int) =
|
||||||
echo "Counter is now: ", button.counter
|
echo "Counter is now: ", button.counter
|
||||||
|
|
||||||
proc appActivate (app: Application) =
|
proc appActivate (app: Application) =
|
||||||
var button: CountButton
|
#var button: CountButton
|
||||||
let window = newApplicationWindow(app)
|
let window = newApplicationWindow(app)
|
||||||
window.title = "Count Button"
|
window.title = "Count Button"
|
||||||
initButton(button, "Counting down from 100 by 5")
|
#initButton(button, "Counting down from 100 by 5") # deprecated
|
||||||
|
let button = newButton(CountButton, "Counting down from 100 by 5")
|
||||||
button.counter = 100
|
button.counter = 100
|
||||||
window.add(button)
|
window.add(button)
|
||||||
button.connect("clicked", buttonClicked, 5)
|
button.connect("clicked", buttonClicked, 5)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "0.7.2"
|
version = "0.7.3"
|
||||||
author = "Stefan Salewski"
|
author = "Stefan Salewski"
|
||||||
description = "High level GObject-Introspection based GTK3/GTK4 bindings"
|
description = "High level GObject-Introspection based GTK3/GTK4 bindings"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language
|
# High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language
|
||||||
# nimpretty --maxLineLen:130 gen.nim
|
# nimpretty --maxLineLen:130 gen.nim
|
||||||
# v 0.7.2 2020-FEB-23
|
# v 0.7.3 2020-MAR-09
|
||||||
# (c) S. Salewski 2018
|
# (c) S. Salewski 2018
|
||||||
|
|
||||||
# https://wiki.gnome.org/Projects/GObjectIntrospection
|
# https://wiki.gnome.org/Projects/GObjectIntrospection
|
||||||
|
|
@ -900,21 +900,29 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
|
||||||
for j in 0.cint ..< gCallableInfoGetNArgs(minfo):
|
for j in 0.cint ..< gCallableInfoGetNArgs(minfo):
|
||||||
let arg = gCallableInfoGetArg(minfo, j)
|
let arg = gCallableInfoGetArg(minfo, j)
|
||||||
assert gArgInfoGetDirection(arg) notin {GIDirection.OUT, INOUT} # so we can ignore this case!
|
assert gArgInfoGetDirection(arg) notin {GIDirection.OUT, INOUT} # so we can ignore this case!
|
||||||
for i in 0 .. 1: # generate the new() and the init() proc
|
for itt in 0 .. 2: # generate the new(), the new(typedesc) and the init() proc
|
||||||
var hhh = "\nproc " & asym & EM & plist
|
var hhh = "\nproc " & asym & EM & plist
|
||||||
if i > 0:
|
if itt == 1: # new(typedesc)
|
||||||
|
let semi = if hhh.contains("()"): "" else: "; "
|
||||||
|
let p = hhh.find("): ")
|
||||||
|
hhh.setLen(p + 1)
|
||||||
|
hhh = hhh.replace("*(", "*(tdesc: typedesc" & semi)
|
||||||
|
hhh.add(": tdesc")
|
||||||
|
if itt == 2: # init(), deprecated
|
||||||
let semi = if hhh.contains("()"): "" else: "; "
|
let semi = if hhh.contains("()"): "" else: "; "
|
||||||
let p = hhh.find("): ")
|
let p = hhh.find("): ")
|
||||||
hhh.setLen(p + 1)
|
hhh.setLen(p + 1)
|
||||||
hhh = hhh.replace("new", "init")
|
hhh = hhh.replace("new", "init")
|
||||||
hhh = hhh.replace("*(", "*[T](result: var T" & semi)
|
hhh = hhh.replace("*(", "*[T](result: var T" & semi)
|
||||||
|
if itt == 2:
|
||||||
|
depStr = " {.deprecated.}"
|
||||||
methodBuffer.writeLine(hhh & depStr & " =")
|
methodBuffer.writeLine(hhh & depStr & " =")
|
||||||
methodBuffer.write(arrLex)
|
methodBuffer.write(arrLex)
|
||||||
methodBuffer.write(sss)
|
methodBuffer.write(sss)
|
||||||
if gCallableInfoCanThrowGerror(minfo):
|
if gCallableInfoCanThrowGerror(minfo):
|
||||||
methodBuffer.writeLine(" var gerror: ptr glib.Error")
|
methodBuffer.writeLine(" var gerror: ptr glib.Error")
|
||||||
if i == 0: arglist.insert(", addr gerror", arglist.high)
|
if itt == 0: arglist.insert(", addr gerror", arglist.high)
|
||||||
if i > 0:
|
if itt == 1 or itt == 2:
|
||||||
methodBuffer.writeLine(" assert(result is $1)" % [manglename(gBaseInfoGetName(info))])
|
methodBuffer.writeLine(" assert(result is $1)" % [manglename(gBaseInfoGetName(info))])
|
||||||
if isGObject:
|
if isGObject:
|
||||||
# CAUTION: some procs are advertised as constructor but do not construct new objects,
|
# CAUTION: some procs are advertised as constructor but do not construct new objects,
|
||||||
|
|
@ -2604,4 +2612,4 @@ proc launch() =
|
||||||
supmod4.close
|
supmod4.close
|
||||||
|
|
||||||
launch()
|
launch()
|
||||||
# 2607 lines
|
# 2615 lines
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue