now we pass handler typed to connect macro and inspect its parameter list
This commit is contained in:
parent
56967c429d
commit
8f23a4781b
1 changed files with 61 additions and 55 deletions
116
gintro/gimpl.nim
116
gintro/gimpl.nim
|
|
@ -29,8 +29,21 @@ proc findSignal(name, obj: NimNode): string =
|
|||
n = getType(n)[1]
|
||||
|
||||
var ProcID: int
|
||||
#
|
||||
macro mconnect(widget: gobject.Object; signal: string; p: untyped; arg: typed; ignoreArg: bool): untyped =
|
||||
# from file gisup.nim we have:
|
||||
# "remove_editable!CellArea!2!(self: CellArea; renderer: CellRenderer; editable: CellEditable | SpinButton | ComboBox | ...
|
||||
# so for signal remove_editable third parameter of handler proc can be CellEditable OR SpinButton OR ComboBox OR ...
|
||||
# This is because SpinButton, ComboBox provides the CellEditable interface!
|
||||
# https://mail.gnome.org/archives/gtk-list/2017-July/msg00018.html
|
||||
# This interface parameter is in most cases the second parameter of handler proc, but can be the third also.
|
||||
macro mconnect(widget: gobject.Object; signal: string; p: typed; arg: typed; ignoreArg: bool): untyped =
|
||||
#echo p.symbol.getImpl().toStrLit
|
||||
#echo p.symbol.getImpl().params.toStrLit
|
||||
#echo p.symbol.getImpl().params[2][1].toStrLit
|
||||
|
||||
var # position and actual type of interface provider, if any
|
||||
ipos = -1
|
||||
ipro: string = nil
|
||||
|
||||
inc(ProcID)
|
||||
let wt = getType(widget)
|
||||
let at = getTypeInst(arg)
|
||||
|
|
@ -41,49 +54,70 @@ macro mconnect(widget: gobject.Object; signal: string; p: untyped; arg: typed; i
|
|||
let procName = "connect_for_signal_" & signalName & $ProcID
|
||||
var sn, wid, num, all, ahl: string
|
||||
let sci = findSignal(signal, wt)
|
||||
var xfaces = newSeq[string]()
|
||||
var r1s = """
|
||||
proc $1$2 {.cdecl.} =
|
||||
let h: pointer = g_object_get_qdata(self, Quark)
|
||||
"""
|
||||
if sci.isNil:
|
||||
if sci.isNil: # the simple signals
|
||||
all = "(self: ptr gobject.Object00; xdata: pointer)"
|
||||
ahl = "(self: gobject.Object)"
|
||||
r1s.add(" $3(cast[$4](h)")
|
||||
if not ignoreArg.boolVal:
|
||||
r1s.add(", cast[$5](xdata)")
|
||||
r1s.add(")\n")
|
||||
else:
|
||||
else: # signals with multiple arguments and maybe using interface providers
|
||||
(sn, wid, num, ahl, all) = sci.split(RecSep)
|
||||
if ahl.contains("|"): # we have to handle interface providers
|
||||
var hargs = ahl.split(";") # handler arguments
|
||||
for i in 0 .. hargs.high: # find the position of the providers, should be second or third argument
|
||||
if hargs[i].contains("|"):
|
||||
ipos = i
|
||||
break
|
||||
assert(ipos >= 0) # indeed assert(ipos > 0) as first parameter should be plain widget/gobject
|
||||
let ipronode = p.symbol.getImpl().params[ipos + 1][1] # the actual data type for interface providers
|
||||
if ipronode.isNil:
|
||||
quit("Error: Signal-Handler has too few parameters: " & $(p.symbol.getImpl().name.toStrLit) & $(p.symbol.getImpl().params.toStrLit))
|
||||
else:
|
||||
ipro = $(ipronode.toStrLit)
|
||||
var ipros = hargs[ipos].split(" | ")
|
||||
ipros[0] = ipros[0].split()[^1]
|
||||
ipros[^1] = ipros[^1].split({';', ')'})[0]
|
||||
if ipros.contains(ipro): # select actual provider -- otherwise handler parameter list does not match, so compile error
|
||||
let ret = hargs[ipos].split("):") # there may be a return value
|
||||
assert(ret.len < 3)
|
||||
hargs[ipos] = hargs[ipos].split(":")[0] & ": " & ipro
|
||||
if ret.len > 1: hargs[ipos].add("):" & ret[1])
|
||||
ahl = hargs.join(";")
|
||||
var resl: string
|
||||
if ahl.contains("): "):
|
||||
resl = all.rsplit("): ", 1)[1]
|
||||
var resu = " $3(cast[$4](h)"
|
||||
if all.find(";") > 0:
|
||||
if all.find(";") > 0: # more than one argument
|
||||
var largs = all.split("; ")
|
||||
largs.delete(0)
|
||||
largs[^1] = largs[^1].split(")")[0]
|
||||
var names, types: array[10, string]
|
||||
var plainArgs = newSeq[string]()
|
||||
for i in 0 .. largs.high:
|
||||
if largs[i].endsWith("00"):
|
||||
(names[i], types[i]) = largs[i].split(": ptr ")
|
||||
types[i].setLen(types[i].len - 2)
|
||||
else:
|
||||
types[i] = nil # plain arg, no object
|
||||
var a1, a2: string
|
||||
(a1, a2) = largs[i].split(": ")
|
||||
let h = ct5nt(a2)
|
||||
if h.len > 0:
|
||||
a1 = h & "(" & a1 & ")"
|
||||
plainArgs.add(a1)
|
||||
for i in 0 .. 9:
|
||||
if names[i].isNil: break
|
||||
resu.add(", " & names[i] & "1")
|
||||
r1s.add(" var " & names[i] & "1: " & types[i] & "\n")
|
||||
r1s.add(" new " & names[i] & "1" & "\n")
|
||||
r1s.add(" " & names[i] & "1.impl = " & names[i] & "\n")
|
||||
for i in plainArgs:
|
||||
resu.add(", " & i)
|
||||
names[i] = a1
|
||||
if ipro != nil: types[ipos - 1] = ipro
|
||||
for i in 0 .. largs.high:
|
||||
if types[i] == nil:
|
||||
resu.add(", " & names[i])
|
||||
else:
|
||||
resu.add(", " & names[i] & "1")
|
||||
r1s.add(" var " & names[i] & "1: " & types[i] & "\n")
|
||||
r1s.add(" new " & names[i] & "1" & "\n")
|
||||
r1s.add(" " & names[i] & "1.impl = " & names[i] & "\n")
|
||||
if not ignoreArg.boolVal:
|
||||
resu.add(", cast[$5](data)")
|
||||
resu.add(")")
|
||||
|
|
@ -92,6 +126,7 @@ proc $1$2 {.cdecl.} =
|
|||
r1s.add(resu & "\n")
|
||||
all = all.replace(")", "; data: pointer)")
|
||||
r1s = r1s % [$procNameCdecl, all, $p, wts, ats]
|
||||
echo r1s
|
||||
result = parseStmt(r1s)
|
||||
if not ignoreArg.boolVal:
|
||||
ahl = ahl.replace(")", "; arg: " & ats & ")")
|
||||
|
|
@ -99,32 +134,15 @@ proc $1$2 {.cdecl.} =
|
|||
ahl = "(self: " & wts & ";" & ahl.split(";", 1)[1]
|
||||
else:
|
||||
ahl = "(self: " & wts & ")" & ahl.split(")", 1)[1]
|
||||
|
||||
var bp = ahl.find("|") # barPosition
|
||||
if bp >= 0:
|
||||
bp = ahl.rfind(" ", bp - 1)
|
||||
ahl.insert(" | ", bp + 1)
|
||||
bp = ahl.rfind("|")
|
||||
bp = ahl.find({';', ')'}, bp + 1)
|
||||
ahl.insert(" | ", bp)
|
||||
#echo ahl
|
||||
let h = ahl.split(" | ")
|
||||
for i in 1 ..< h.high:
|
||||
xfaces.add(h[0] & h[i] & h[^1])
|
||||
else:
|
||||
xfaces.add(ahl)
|
||||
|
||||
#for i in xfaces: echo i
|
||||
|
||||
for ahlface in xfaces:
|
||||
let r2s =
|
||||
if ignoreArg.boolVal:
|
||||
"""
|
||||
let r2s =
|
||||
if ignoreArg.boolVal:
|
||||
"""
|
||||
proc $1(self: $2; p: proc $3): culong {.discardable.} =
|
||||
sc$4(self, $5, nil)
|
||||
""" % [$procName, wts, ahlface, signalName, $procNameCdecl, $(widget.toStrLit), $p]
|
||||
else:
|
||||
"""
|
||||
$1($6, $7)
|
||||
""" % [$procName, wts, ahl, signalName, $procNameCdecl, $(widget.toStrLit), $p]
|
||||
else:
|
||||
"""
|
||||
proc $1(self: $2; p: proc $3; a: $4): culong {.discardable.} =
|
||||
when a is RootRef:
|
||||
GC_ref(a)
|
||||
|
|
@ -135,27 +153,15 @@ proc $1(self: $2; p: proc $3; a: $4): culong {.discardable.} =
|
|||
deepCopy(ar[], a)
|
||||
GC_ref(ar)
|
||||
sc$5(self, $6, cast[pointer](ar[]))
|
||||
|
||||
""" % [$procName, wts, ahlface, ats, signalName, $procNameCdecl, $(widget.toStrLit), $p, $(arg.toStrLit)]
|
||||
result.add(parseStmt(r2s))
|
||||
#echo r2s
|
||||
|
||||
let r2s =
|
||||
if ignoreArg.boolVal:
|
||||
"""
|
||||
$1($6, $7)
|
||||
""" % [$procName, wts, ahl, signalName, $procNameCdecl, $(widget.toStrLit), $p]
|
||||
else:
|
||||
"""
|
||||
$1($7, $8, $9)
|
||||
""" % [$procName, wts, ahl, ats, signalName, $procNameCdecl, $(widget.toStrLit), $p, $(arg.toStrLit)]
|
||||
echo r2s
|
||||
result.add(parseStmt(r2s))
|
||||
#echo r2s
|
||||
|
||||
template connect*(widget: gobject.Object; signal: string; p: untyped; arg: typed): untyped =
|
||||
template connect*(widget: gobject.Object; signal: string; p: typed; arg: typed): untyped =
|
||||
mconnect(widget, signal, p, arg, false)
|
||||
|
||||
template connect*(widget: gobject.Object; signal: string; p: untyped): untyped =
|
||||
template connect*(widget: gobject.Object; signal: string; p: typed): untyped =
|
||||
mconnect(widget, signal, p, "", true)
|
||||
|
||||
var TimeoutID: int
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue