various fixes

This commit is contained in:
Stefan Salewski 2019-04-14 12:56:38 +02:00
commit 8a59ea33d0
5 changed files with 668 additions and 50 deletions

View file

@ -841,14 +841,13 @@ main()
== A more advanced example for cairo drawing with zooming, panning, scrolling
The following code is a plain Nim version of a drawing demo which I wrote some years ago in Ruby (http://ssalewski.de/PetEd-Demo.html.en).
With the latest fix to Nim GTK3 bingings it seems to work fine, but some rewriting for optimized performance
may be needed, I have to investigate that.
With the latest fix to Nim GTK3 bindings it seems to work fine, but some rewriting for optimized performance
may be needed, I have to investigate that. Cairo surface is currently manually freed, because GC may have a too large delay.
Later we may use Destructors for that.
NOTE: The latest needed gintro patch is not yet available, I will provide it soon...
[[cairo2.nim]]
[[drawingarea.nim]]
[source,nim]
.cairo2.nim
.drawingarea.nim
----
# Plain demo for zooming, panning, scrolling with GTK DrawingArea
# (c) S. Salewski, 21-DEC-2010 (initial Ruby version)
@ -879,7 +878,7 @@ proc drawWorld(cr: cairo.Context) =
cr.rectangle(DataX, DataY, DataWidth, DataHeight)
var i = 10.0
while true:
if [DataWidth - 2.0 * i, DataHeight - 2.0 * i].min <= 0:
if min(DataWidth - 2.0 * i, DataHeight - 2.0 * i) <= 0:
break
cr.rectangle(DataX + i, DataY + i, DataWidth - 2.0 * i,
DataHeight - 2.0 * i)
@ -933,7 +932,7 @@ proc newPosAdj: PosAdj =
initAdjustment(result, 0, 0, 1, 1, 10, 1)
type
PDA = ref object of Table
PDA = ref object of Grid
zoomNearMousepointer: bool
selecting: bool
userZoom: float
@ -973,7 +972,7 @@ proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool =
# clamp to correct values, 0 <= value <= (adj.upper - adj.pageSize), block calling onAdjustmentEvent()
proc updateVal(adj: PosAdj; d: float) =
adj.signalHandlerBlock(adj.handlerID)
adj.setValue([0.0, [adj.value + d, adj.upper - adj.pageSize].min].max)
adj.setValue(max(0.0, min(adj.value + d, adj.upper - adj.pageSize)))
adj.signalHandlerUnblock(adj.handlerID)
proc updateAdjustments(this: PDA; dx, dy: float) =
@ -1007,8 +1006,8 @@ proc dareaConfigureCallback(darea: DrawingArea; event: EventConfigure;
this.updateAdjustments(0, 0)
(this.dataX, this.dataY, this.dataWidth,
this.dataHeight) = getWorldExtends() # query user defined size
this.fullScale = [this.darea.allocatedWidth.float / this.dataWidth,
this.darea.allocatedHeight.float / this.dataHeight].min
this.fullScale = min(this.darea.allocatedWidth.float / this.dataWidth,
this.darea.allocatedHeight.float / this.dataHeight)
this.paint
proc updateAdjustmentsAndPaint(this: PDA; dx, dy: float) =
@ -1017,11 +1016,17 @@ proc updateAdjustmentsAndPaint(this: PDA; dx, dy: float) =
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth,
this.darea.allocatedHeight)
# event coordinates to user space
proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
((eventX - this.hadjustment.upper * 0.5 + this.hadjustment.value) / (
this.fullScale * this.userZoom) + this.dataX + this.dataWidth * 0.5,
(eventY - this.vadjustment.upper * 0.5 + this.vadjustment.value) / (
this.fullScale * this.userZoom) + this.dataY + this.dataHeight * 0.5)
proc onMotion(darea: DrawingArea; event: EventMotion; this: PDA): bool =
var state: ModifierType
discard event.state(state)
var x, y: float
discard event.getCoords(x, y)
let state = getState(event)
let (x, y) = event.getCoords
#(x, y) = this.getUserCoordinates(x, y)
if (state.contains(button1)): # selecting
this.selecting = true
this.zoomRectX1 = x
@ -1040,10 +1045,8 @@ proc onMotion(darea: DrawingArea; event: EventMotion; this: PDA): bool =
# is the relative movement caused by zooming
proc scrollEvent(darea: DrawingArea; event: EventScroll; this: PDA): bool =
let z0 = this.userZoom
var d: ScrollDirection
discard scrollDirection(event, d)
var x, y: float
discard event.getCoords(x, y)
var d = getScrollDirection(event)
var (x, y) = event.getCoords
if d == ScrollDirection.up:
this.userZoom *= ZOOM_FACTOR_MOUSE_WHEEL
elif d == ScrollDirection.down:
@ -1059,38 +1062,30 @@ proc scrollEvent(darea: DrawingArea; event: EventScroll; this: PDA): bool =
this.updateAdjustmentsAndPaint((this.hadjustment.value +
this.darea.allocatedWidth.float * 0.5) * (this.userZoom / z0 - 1),
(this.vadjustment.value +
this.darea.allocatedHeight.float * 0.5) * (this.userZoom / z0 - 1))
# event coordinates to user space
proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
((eventX - this.hadjustment.upper * 0.5 + this.hadjustment.value) / (
this.fullScale * this.userZoom) + this.dataX + this.dataWidth * 0.5,
(eventY - this.vadjustment.upper * 0.5 + this.vadjustment.value) / (
this.fullScale * this.userZoom) + this.dataY + this.dataHeight * 0.5)
this.darea.allocatedHeight.float * 0.5) * (
this.userZoom / z0 - 1))
proc buttonPressEvent(darea: DrawingArea; event: EventButton;
this: PDA): bool =
var x, y: float
discard event.getCoords(x, y)
(x, y) = this.getUserCoordinates(x, y)
echo "User coordinates: ", x, ' ', y, "\n" # to verify getUserCoordinates()
var (x, y) = event.getCoords
this.lastMousePosX = x
this.lastMousePosY = y
this.lastButtonDownPosX = x
this.lastButtonDownPosY = y
echo "buttonPressEvent", x, " ", y
(x, y) = this.getUserCoordinates(x, y)
echo "User coordinates: ", x, ' ', y, "\n" # to verify getUserCoordinates()
# zoom into selected rectangle and center it
proc buttonReleaseEvent(darea: DrawingArea; event: EventButton;
this: PDA): bool =
var x, y: float
discard event.getCoords(x, y)
var b: int
discard button(event, b)
var (x, y) = event.getCoords
var b = getButton(event)
if b == 1:
this.selecting = false
let z1 = [this.darea.allocatedWidth.float / (
let z1 = min(this.darea.allocatedWidth.float / (
this.lastButtonDownPosX - x).abs, this.darea.allocatedHeight.float / (
this.lastButtonDownPosY - y).abs].min
this.lastButtonDownPosY - y).abs)
if z1 < ZOOM_FACTOR_SELECT_MAX: # else selection rectangle will persist, we may output a message...
this.userZoom *= z1
this.updateAdjustmentsAndPaint(
@ -1105,13 +1100,14 @@ proc onAdjustmentEvent(this: PosAdj; pda: PDA) =
pda.darea.allocatedHeight)
proc newPDA: PDA =
initTable(result, 2, 2, false)
initGrid(result)
result.zoomNearMousepointer = ZOOM_NEAR_MOUSEPOINTER # mouse wheel zooming
result.selecting = false
result.userZoom = 1.0
result.surf = nil
result.darea = newDrawingArea()
result.darea.setHExpand#(true)
result.darea.setVExpand#(true)
result.darea.connect("draw", drawingAreaDrawCb, result)
result.darea.connect("configure-event", dareaConfigureCallback, result)
result.darea.addEvents({EventFlag.buttonPress, EventFlag.buttonRelease,
@ -1130,12 +1126,11 @@ proc newPDA: PDA =
onAdjustmentEvent, result)
result.hscrollbar = newScrollbar(Orientation.horizontal, result.hadjustment)
result.vscrollbar = newScrollbar(Orientation.vertical, result.vadjustment)
result.attach(result.darea, 0, 1, 0, 1, {AttachFlag.expand, AttachFlag.fill}, {
AttachFlag.expand, AttachFlag.fill}, 0, 0)
result.attach(result.hscrollbar, 0, 1, 1, 2, {AttachFlag.expand,
AttachFlag.fill}, {}, 0, 0)
result.attach(result.vscrollbar, 1, 2, 0, 1, {}, {AttachFlag.expand,
AttachFlag.fill}, 0, 0)
result.hscrollbar.setHExpand#(true)
result.vscrollbar.setVExpand#(true)
result.attach(result.darea, 0, 0, 1, 1)
result.attach(result.vscrollbar, 1, 0, 1, 1)
result.attach(result.hscrollbar, 0, 1, 1, 1)
proc appActivate(app: Application) =
let window = newApplicationWindow(app)

297
examples/drawingarea.nim Normal file
View file

@ -0,0 +1,297 @@
# Plain demo for zooming, panning, scrolling with GTK DrawingArea
# (c) S. Salewski, 21-DEC-2010 (initial Ruby version)
# Nim version April 2019 -- well first draft :-)
# License MIT
import gintro/[gtk, gdk, glib, gobject, gio, cairo]
const
DataX = 150.0
DataY = 250.0
DataWidth = 200.0
DataHeight = 120.0
# The following two functions are intended to be user defined -- we have still
# to investigate how to do that best.
# bounding box of user data -- x, y, w, h -- top left corner, width, height
proc getWorldExtends(): (float, float, float, float) =
(DataX, DataY, DataWidth, DataHeight) # current extents of our user world
# draw to cairo context
proc drawWorld(cr: cairo.Context) =
cr.setSource(1, 1, 1)
cr.paint
cr.setSource(0, 0, 0)
cr.setLineWidth(2)
cr.rectangle(DataX, DataY, DataWidth, DataHeight)
var i = 10.0
while true:
if min(DataWidth - 2.0 * i, DataHeight - 2.0 * i) <= 0:
break
cr.rectangle(DataX + i, DataY + i, DataWidth - 2.0 * i,
DataHeight - 2.0 * i)
i += 10.0
cr.stroke
const
ZOOM_FACTOR_MOUSE_WHEEL = 1.1
ZOOM_FACTOR_SELECT_MAX = 10 # ignore zooming in tiny selection
ZOOM_NEAR_MOUSEPOINTER = true # mouse wheel zooming -- to mousepointer or center
SELECT_RECT_COL = [0.0, 0, 1, 0.5] # blue with transparency
discard """
Zooming, scrolling, panning...
|-------------------------|
|<-------- A ------------>|
| |
| |---------------| |
| | <---- a ----->| |
| | visible | |
| |---------------| |
| |
| |
|-------------------------|
a is the visible, zoomed in area == darea.allocatedWidth
A is the total data range
A/a == userZoom >= 1
For horizontal adjustment we use
hadjustment.setUpper(darea.allocatedWidth * userZoom) == A
hadjustment.setPageSize(darea.allocatedWidth) == a
So hadjustment.value == left side of visible area
Initially, we set userZoom = 1, scale our data to fit into darea.allocatedWidth
and translate the origin of our data to (0, 0)
Zooming: Mouse wheel or selecting a rectangle with left mouse button pressed
Scrolling: Scrollbars
Panning: Moving mouse while middle mouse button pressed
"""
# drawing area and scroll bars in 2x2 table (PDA == Plain Drawing Area)
type
PosAdj = ref object of Adjustment
handlerID: uint64
proc newPosAdj: PosAdj =
initAdjustment(result, 0, 0, 1, 1, 10, 1)
type
PDA = ref object of Grid
zoomNearMousepointer: bool
selecting: bool
userZoom: float
surf: Surface
darea: DrawingArea
hadjustment: PosAdj
vadjustment: PosAdj
hscrollbar: Scrollbar
vscrollbar: Scrollbar
fullScale: float
dataX: float
dataY: float
dataWidth: float
dataHeight: float
lastButtonDownPosX: float
lastButtonDownPosY: float
lastMousePosX: float
lastMousePosY: float
zoomRectX1: float
zoomRectY1: float
proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool =
if this.surf.isNil: return
cr.setSource(patternCreateForSurface(this.surf))
cr.paint
if this.selecting:
cr.rectangle(this.lastButtonDownPosX, this.lastButtonDownPosY,
this.zoomRectX1 - this.lastButtonDownPosX,
this.zoomRectY1 - this.lastButtonDownPosY)
cr.setSource(0, 0, 1, 0.5) # SELECT_RECT_COL) # 0, 0, 1, 0.5
cr.fillPreserve
cr.setSource(0, 0, 0)
cr.setLineWidth(2)
cr.stroke
return true # TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
# clamp to correct values, 0 <= value <= (adj.upper - adj.pageSize), block calling onAdjustmentEvent()
proc updateVal(adj: PosAdj; d: float) =
adj.signalHandlerBlock(adj.handlerID)
adj.setValue(max(0.0, min(adj.value + d, adj.upper - adj.pageSize)))
adj.signalHandlerUnblock(adj.handlerID)
proc updateAdjustments(this: PDA; dx, dy: float) =
this.hadjustment.setUpper(this.darea.allocatedWidth.float * this.userZoom)
this.vadjustment.setUpper(this.darea.allocatedHeight.float *
this.userZoom)
this.hadjustment.setPageSize(this.darea.allocatedWidth.float)
this.vadjustment.setPageSize(this.darea.allocatedHeight.float)
updateVal(this.hadjustment, dx)
updateVal(this.vadjustment, dy)
# Maybe we should fix this for latest GTK3, see
# https://developer.gnome.org/gdk3/stable/gdk3-Cairo-Interaction.html
# so use gdk_drawing_context_get_cairo_context ()
# or maybe even better do all drwing from within "draw" callback?
proc paint(this: PDA) =
if this.surf != nil:
cairosurfaceDestroy(this.surf.impl) # we may have to fix that later for automatically destroy
this.surf = this.darea.window.createSimilarSurface(Content.color,
this.darea.allocatedWidth, this.darea.allocatedHeight)
let cr = newContext(this.surf)
cr.translate(this.hadjustment.upper * 0.5 - this.hadjustment.value, # our origin is the center
this.vadjustment.upper * 0.5 - this.vadjustment.value)
cr.scale(this.fullScale * this.userZoom, this.fullScale * this.userZoom)
cr.translate(-this.dataX - this.dataWidth * 0.5,
-this.dataY - this.dataHeight * 0.5)
drawWorld(cr) # call the user provided drawing fonction
proc dareaConfigureCallback(darea: DrawingArea; event: EventConfigure;
this: PDA): bool =
this.updateAdjustments(0, 0)
(this.dataX, this.dataY, this.dataWidth,
this.dataHeight) = getWorldExtends() # query user defined size
this.fullScale = min(this.darea.allocatedWidth.float / this.dataWidth,
this.darea.allocatedHeight.float / this.dataHeight)
this.paint
proc updateAdjustmentsAndPaint(this: PDA; dx, dy: float) =
this.updateAdjustments(dx, dy)
this.paint
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth,
this.darea.allocatedHeight)
# event coordinates to user space
proc getUserCoordinates(this: PDA; eventX, eventY: float): (float, float) =
((eventX - this.hadjustment.upper * 0.5 + this.hadjustment.value) / (
this.fullScale * this.userZoom) + this.dataX + this.dataWidth * 0.5,
(eventY - this.vadjustment.upper * 0.5 + this.vadjustment.value) / (
this.fullScale * this.userZoom) + this.dataY + this.dataHeight * 0.5)
proc onMotion(darea: DrawingArea; event: EventMotion; this: PDA): bool =
let state = getState(event)
let (x, y) = event.getCoords
#(x, y) = this.getUserCoordinates(x, y)
if (state.contains(button1)): # selecting
this.selecting = true
this.zoomRectX1 = x
this.zoomRectY1 = y
this.darea.queueDrawArea(0, 0, this.darea.allocatedWidth,
this.darea.allocatedHeight)
elif button2 in state: # panning
this.updateAdjustmentsAndPaint(this.lastMousePosX - x,
this.lastMousePosY - y)
this.lastMousePosX = x
this.lastMousePosY = y
#event.request # request more motion events ?
# zooming with mouse wheel -- data near mouse pointer should not move if possible!
# hadjustment.value + event.x is the position in our zoomed_in world, (userZoom / z0 - 1)
# is the relative movement caused by zooming
proc scrollEvent(darea: DrawingArea; event: EventScroll; this: PDA): bool =
let z0 = this.userZoom
var d = getScrollDirection(event)
var (x, y) = event.getCoords
if d == ScrollDirection.up:
this.userZoom *= ZOOM_FACTOR_MOUSE_WHEEL
elif d == ScrollDirection.down:
this.userZoom /= ZOOM_FACTOR_MOUSE_WHEEL
if (this.userZoom < 1):
this.userZoom = 1
if this.zoomNearMousepointer:
this.updateAdjustmentsAndPaint((this.hadjustment.value + x) * (
this.userZoom / z0 - 1),
(this.vadjustment.value + y) * (
this.userZoom / z0 - 1))
else: # zoom to center
this.updateAdjustmentsAndPaint((this.hadjustment.value +
this.darea.allocatedWidth.float * 0.5) * (this.userZoom / z0 - 1),
(this.vadjustment.value +
this.darea.allocatedHeight.float * 0.5) * (
this.userZoom / z0 - 1))
proc buttonPressEvent(darea: DrawingArea; event: EventButton;
this: PDA): bool =
var (x, y) = event.getCoords
this.lastMousePosX = x
this.lastMousePosY = y
this.lastButtonDownPosX = x
this.lastButtonDownPosY = y
echo "buttonPressEvent", x, " ", y
(x, y) = this.getUserCoordinates(x, y)
echo "User coordinates: ", x, ' ', y, "\n" # to verify getUserCoordinates()
# zoom into selected rectangle and center it
proc buttonReleaseEvent(darea: DrawingArea; event: EventButton;
this: PDA): bool =
var (x, y) = event.getCoords
var b = getButton(event)
if b == 1:
this.selecting = false
let z1 = min(this.darea.allocatedWidth.float / (
this.lastButtonDownPosX - x).abs, this.darea.allocatedHeight.float / (
this.lastButtonDownPosY - y).abs)
if z1 < ZOOM_FACTOR_SELECT_MAX: # else selection rectangle will persist, we may output a message...
this.userZoom *= z1
this.updateAdjustmentsAndPaint(
((2 * this.hadjustment.value + x + this.lastButtonDownPosX) * z1 -
this.darea.allocatedWidth.float) * 0.5 - this.hadjustment.value,
((2 * this.vadjustment.value + y + this.lastButtonDownPosY) * z1 -
this.darea.allocatedHeight.float) * 0.5 - this.vadjustment.value)
proc onAdjustmentEvent(this: PosAdj; pda: PDA) =
pda.paint
pda.darea.queueDrawArea(0, 0, pda.darea.allocatedWidth,
pda.darea.allocatedHeight)
proc newPDA: PDA =
initGrid(result)
result.zoomNearMousepointer = ZOOM_NEAR_MOUSEPOINTER # mouse wheel zooming
result.selecting = false
result.userZoom = 1.0
result.surf = nil
result.darea = newDrawingArea()
result.darea.setHExpand#(true)
result.darea.setVExpand#(true)
result.darea.connect("draw", drawingAreaDrawCb, result)
result.darea.connect("configure-event", dareaConfigureCallback, result)
result.darea.addEvents({EventFlag.buttonPress, EventFlag.buttonRelease,
EventFlag.scroll,
EventFlag.button1Motion, EventFlag.button2Motion,
EventFlag.pointerMotionHint})
result.darea.connect("motion-notify-event", onMotion, result)
result.darea.connect("scroll_event", scrollEvent, result)
result.darea.connect("button_press_event", buttonPressEvent, result)
result.darea.connect("button_release_event", buttonReleaseEvent, result)
result.hadjustment = newPosAdj()
result.hadjustment.handlerID = result.hadjustment.connect("value-changed",
onAdjustmentEvent, result)
result.vadjustment = newPosAdj()
result.vadjustment.handlerID = result.vadjustment.connect("value-changed",
onAdjustmentEvent, result)
result.hscrollbar = newScrollbar(Orientation.horizontal, result.hadjustment)
result.vscrollbar = newScrollbar(Orientation.vertical, result.vadjustment)
result.hscrollbar.setHExpand#(true)
result.vscrollbar.setVExpand#(true)
result.attach(result.darea, 0, 0, 1, 1)
result.attach(result.vscrollbar, 1, 0, 1, 1)
result.attach(result.hscrollbar, 0, 1, 1, 1)
proc appActivate(app: Application) =
let window = newApplicationWindow(app)
window.title = "Drawing example"
window.defaultSize = (400, 400)
let pda = newPDA()
window.add(pda)
showAll(window)
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", appActivate)
discard run(app)
main()

View file

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

View file

@ -145,7 +145,7 @@ proc $1$2 {.cdecl.} =
r1s.add(resu & "\n")
all = all.replace(")", "; data: pointer)")
r1s = r1s % [$procNameCdecl, all, $p, wts, ats]
echo r1s
#echo r1s
result = parseStmt(r1s)
if not ignoreArg.boolVal:
ahl = ahl.replace(")", "; arg: " & ats & ")")
@ -175,7 +175,7 @@ proc $1(self: $2; p: proc $3; a: $4): culong {.discardable.} =
sc$5(self, $6, cast[pointer](ar[]))
$1($7, $8, $9)
""" % [$procName, wts, ahl, ats, signalName, $procNameCdecl, $(widget.toStrLit), $p, $(arg.toStrLit)]
echo r2s
#echo r2s
result.add(parseStmt(r2s))
template connect*(widget: gobject.Object; signal: string; p: typed; arg: typed): untyped =

View file

@ -1,5 +1,5 @@
# High level gobject-introspection based GTK3 bindings for the Nim programming language
# v 0.4.12 2019-APR-11
# v 0.4.12 2019-APR-14
# (c) S. Salewski 2018
# https://wiki.gnome.org/Projects/GObjectIntrospection
@ -460,6 +460,12 @@ proc genP(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): (str
if genProxy and (str == "string" or str == "cstring") and mayBeNil: # v0.4.11
#str.add(" = nil")
str.add(" = \"\"")
if genProxy and m == 0:
if sym.contains("_set_") and str == "bool":
#echo "TTTTTTTTTT", sym
str.add(" = true")
if genProxy and isProxyCandidate(t) and mayBeNil:
#if not str.contains("|") and (gArgInfoGetDirection(arg) == GIDirection.OUT or gArgInfoGetDirection(arg) == GIDirection.INOUT):
# str.add(" = cast[" & str & "](nil)")
@ -573,6 +579,15 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
var ret2 = gCallableInfoGetReturnType(minfo)
#var ret22 = gCallableInfoGetReturnType(minfo)
for run in 0 .. 1:
#if run == 0:
# if asym.startsWith("set"):
# if gCallableInfoGetNArgs(minfo) == 1 or (gCallableInfoIsMethod(minfo) and gCallableInfoGetNArgs(minfo) == 2):
# echo "XXXXXXXXXX", asym, " ", gCallableInfoGetNArgs(minfo)
if run == 1:
#if not (asym != "errorQuark" and asym != "getPlugin" and asym != "quark"): continue
@ -589,6 +604,10 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
asym = asym[3 .. ^1]
asym[0] = asym[0].toLowerAscii
if asym.startsWith("set"):
#if plist.contains(" = true"):
#echo "ZZZZZZ ", plist, " ", arglist
plist = plist.replace(": bool = true", ": bool")
asym = asym[3 .. ^1]
asym[0] = asym[0].toLowerAscii
asym = '`' & asym & '=' & '`'
@ -601,12 +620,18 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo; genProxy = false) =
if gBaseInfoGetType(iface) == GIInfoType.Object and gBaseInfoGetName(iface) != "ParamSpec":
isGObject = true
(plist, arglist, replist) = genP(mInfo, true, info)
if asym[^2] == '=':
plist = plist.replace(": bool = true", ": bool")
if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0:
if info != nil:
asym = asym.replace("new", "new" & manglename(gBaseInfoGetName(info)))
if fixedProcNames.contains(sym):
asym = fixedProcNames[sym]
for i in 0 .. 1:
#if i > 0 and isGObject:
# echo "XYZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ", asym
var hhh = "\nproc " & asym & EM & plist
if i > 0:
let semi = if hhh.contains("()"): "" else: "; "
@ -1401,6 +1426,237 @@ proc processInfo(i: GIBaseInfo) =
writeConst(i)
else: assert(false)
# Gtk objects builder may provide. Only for Gtk module, so Gtk prefix is assume.
# Other objects loke gtkSourceView are separated!
# This a guessed list, so it may be inaccurate.
const GtkBuilderObjects = """
AboutDialog
AccelLabel
ActionBar
ActionGroup
Alignment
AppChooserButton
AppChooserDialog
AppChooserWidget
Application
ApplicationWindow
Arrow
AspectFrame
Assistant
Box
Builder
Button
ButtonBox
Calendar
CellAreaBox
CellView
CheckButton
CheckMenuItem
ColorButton
ColorChooserDialog
ColorChooserWidget
ColorSelectionDialog
ComboBox
ComboBoxText
Dialog
DrawingArea
Entry
EntryCompletion
EventBox
Expander
FileChooserButton
FileChooserNative
FileChooserWidget
FileFilter
Fixed
FlowBox
FontButton
FontChooserDialog
FontChooserWidget
FontSelection
FontSelectionDialog
Frame
GLArea
Grid
HandleBox
HBox
HButtonBox
HeaderBar
HPaned
HScale
HScrollbar
HSeparator
IconView
ImageMenuItem
InfoBar
Invisible
Label
Layout
LevelBar
LinkButton
ListBox
ListBoxRow
ListStore
LockButton
Menu
MenuBar
MenuButton
MenuItem
MenuToolButton
ModelButton
Notebook
OffscreenWindow
Overlay
Paned
PlacesSidebar
Popover
PopoverMenu
ProgressBar
RadioButton
RadioMenuItem
RadioToolButton
RecentChooserMenu
RecentChooserWidget
RecentManager
Revealer
Scale
ScaleButton
Scrollbar
ScrolledWindow
SearchBar
SearchEntry
Separator
SeparatorMenuItem
SeparatorToolItem
ShortcutLabel
SizeGroup
SpinButton
Spinner
Stack
StackSidebar
StackSwitcher
Statusbar
Style
Switch
Table
TearoffMenuItem
TextView
ToggleButton
ToggleToolButton
Toolbar
ToolButton
ToolItem
ToolItemGroup
ToolPalette
TreeStore
TreeView
TreeViewColumn
VBox
VButtonBox
Viewport
VolumeButton
VPaned
VScrollbar
VSeparator
Window
"""
const GTK_SOURCE_EPI = """
proc getView(builder: Builder; name: string): View =
new result
let gt = g_type_from_name("GSource")
assert(gt != 0)
result.impl = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name)
assert(toBool(g_type_check_instance_is_a(cast[ptr TypeInstance00](result.impl), gt)))
proc completionContextGetType*(): GType {.importc: "gtk_source_completion_context_get_type", libprag.}
proc completionProviderGetType*(): GType {.importc: "gtk_source_completion_provider_get_type", libprag.}
proc completionWordsGetType*(): GType {.importc: "gtk_source_completion_words_get_type", libprag.}
proc bufferGetType*(): GType {.importc: "gtk_source_buffer_get_type", libprag.}
proc completionGetType*(): GType {.importc: "gtk_source_completion_get_type", libprag.}
proc completionInfoGetType*(): GType {.importc: "gtk_source_completion_info_get_type", libprag.}
proc completionItemGetType*(): GType {.importc: "gtk_source_completion_item_get_type", libprag.}
proc completionProposalGetType*(): GType {.importc: "gtk_source_completion_proposal_get_type", libprag.}
proc encodingGetType*(): GType {.importc: "gtk_source_encoding_get_type", libprag.}
proc fileGetType*(): GType {.importc: "gtk_source_file_get_type", libprag.}
proc fileLoaderGetType*(): GType {.importc: "gtk_source_file_loader_get_type", libprag.}
proc fileSaverGetType*(): GType {.importc: "gtk_source_file_saver_get_type", libprag.}
proc gutterGetType*(): GType {.importc: "gtk_source_gutter_get_type", libprag.}
proc gutterRendererGetType*(): GType {.importc: "gtk_source_gutter_renderer_get_type", libprag.}
proc gutterRendererTextGetType*(): GType {.importc: "gtk_source_gutter_renderer_text_get_type", libprag.}
proc gutterRendererPixbufGetType*(): GType {.importc: "gtk_source_gutter_renderer_pixbuf_get_type", libprag.}
proc languageGetType*(): GType {.importc: "gtk_source_language_get_type", libprag.}
proc languageManagerGetType*(): GType {.importc: "gtk_source_language_manager_get_type", libprag.}
proc viewGetType*(): GType {.importc: "gtk_source_view_get_type", libprag.}
proc mapGetType*(): GType {.importc: "gtk_source_map_get_type", libprag.}
proc markGetType*(): GType {.importc: "gtk_source_mark_get_type", libprag.}
proc markAttributesGetType*(): GType {.importc: "gtk_source_mark_attributes_get_type", libprag.}
proc printCompositorGetType*(): GType {.importc: "gtk_source_print_compositor_get_type", libprag.}
proc regionGetType*(): GType {.importc: "gtk_source_region_get_type", libprag.}
proc searchContextGetType*(): GType {.importc: "gtk_source_search_context_get_type", libprag.}
proc searchSettingsGetType*(): GType {.importc: "gtk_source_search_settings_get_type", libprag.}
proc spaceDrawerGetType*(): GType {.importc: "gtk_source_space_drawer_get_type", libprag.}
proc styleGetType*(): GType {.importc: "gtk_source_style_get_type", libprag.}
proc styleSchemeGetType*(): GType {.importc: "gtk_source_style_scheme_get_type", libprag.}
proc styleSchemeChooserGetType*(): GType {.importc: "gtk_source_style_scheme_chooser_get_type", libprag.}
proc styleSchemeChooserButtonGetType*(): GType {.importc: "gtk_source_style_scheme_chooser_button_get_type", libprag.}
proc styleSchemeChooserWidgetGetType*(): GType {.importc: "gtk_source_style_scheme_chooser_widget_get_type", libprag.}
proc styleSchemeManagerGetType*(): GType {.importc: "gtk_source_style_scheme_manager_get_type", libprag.}
proc tagGetType*(): GType {.importc: "gtk_source_tag_get_type", libprag.}
proc undoManagerGetType*(): GType {.importc: "gtk_source_undo_manager_get_type", libprag.}
proc completionWordsProposalGetType*(): GType {.importc: "gtk_source_completion_words_proposal_get_type", libprag.}
proc completionWordsLibraryGetType*(): GType {.importc: "gtk_source_completion_words_library_get_type", libprag.}
proc completionWordsBufferGetType*(): GType {.importc: "gtk_source_completion_words_buffer_get_type", libprag.}
# register the GObject types so builder can use them, see
# https://mail.gnome.org/archives/gtk-list/2015-March/msg00016.html
discard viewGetType()
discard completionInfoGetType()
discard styleSchemeChooserButtonGetType()
"""
const GDK_EPI = """
proc gdk_window_invalidate_nilrect(self: ptr Window00; rect: ptr Rectangle; invalidateChildren: gboolean) {.
@ -1419,6 +1675,60 @@ proc fixednewCursorFromName*(display: Display; name: string): Cursor =
#assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
proc getAngle*(self: SomeEvent; event2: SomeEvent): cdouble =
if not toBool(gdk_events_get_angle(cast[ptr Event00](self.impl), cast[ptr Event00](event2.impl), result)):
raise newException(Defect, "Events do not support getAngle().")
proc getCenter*(self: SomeEvent; event2: SomeEvent): (cdouble, cdouble) =
if not toBool(gdk_events_get_center(cast[ptr Event00](self.impl), cast[ptr Event00](event2.impl), result[0], result[1])):
raise newException(Defect, "Events do not support getCenter().")
proc getDistance*(self: SomeEvent; event2: SomeEvent): cdouble =
if not toBool(gdk_events_get_distance(cast[ptr Event00](self.impl), cast[ptr Event00](event2.impl), result)):
raise newException(Defect, "Events do not support getDistance().")
proc getAxis*(self: SomeEvent; axisUse: AxisUse): cdouble =
if not toBool(gdk_event_get_axis(cast[ptr Event00](self.impl), axisUse, result)):
raise newException(Defect, "Event does not support getAxis().")
proc getButton*(self: SomeEvent): int =
var button: uint32
if not toBool(gdk_event_get_button(cast[ptr Event00](self.impl), button)):
raise newException(Defect, "Event don't has a button field.")
return int(button)
proc getClickCount*(self: SomeEvent): int =
var clickCount_00: uint32
if not toBool(gdk_event_get_click_count(cast[ptr Event00](self.impl), clickCount_00)):
raise newException(Defect, "Event does not support getClickCount().")
return int(clickCount_00)
proc getCoords*(self: SomeEvent): (cdouble, cdouble) =
if not toBool(gdk_event_get_coords(cast[ptr Event00](self.impl), result[0], result[1])):
raise newException(Defect, "This event don't has a coordinate field.")
proc getKeyval*(self: SomeEvent): int =
var keyval_00 = uint32
if not toBool(gdk_event_get_keyval(cast[ptr Event00](self.impl), keyval_00)):
raise newException(Defect, "This event don't has a keyval field.")
return int(keyval_00)
proc getRootCoords*(self: SomeEvent): (cdouble, cdouble) =
if not toBool(gdk_event_get_root_coords(cast[ptr Event00](self.impl), result[0], result[1])):
raise newException(Defect, "This event don't has a rootCoordinate field.")
proc getScrollDeltas*(self: SomeEvent): (cdouble, cdouble) =
if not toBool(gdk_event_get_scroll_deltas(cast[ptr Event00](self.impl), result[0], result[1])):
raise newException(Defect, "This event don't has a scrollDeltas field.")
proc getScrollDirection*(self: SomeEvent): ScrollDirection =
if not toBool(gdk_event_get_scroll_direction(cast[ptr Event00](self.impl), result)):
raise newException(Defect, "Event don't has a scrollDirection field.")
proc getState*(self: SomeEvent): ModifierType =
if not toBool(gdk_event_get_state(cast[ptr Event00](self.impl), result)):
raise newException(Defect, "Event don't has a state field.")
"""
const GIO_EPI = """
@ -1801,12 +2111,28 @@ proc main(namespace: string) =
if namespace == "Gtk":
output.write(GTK_EPI)
for i in GtkBuilderObjects.split:
if i == "": continue
output.write("""
proc get$1*(builder: Builder; name: string): $1 =
new result
let gt = g_type_from_name("Gtk$1")
assert(gt != 0)
result.impl = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name)
assert(toBool(g_type_check_instance_is_a(cast[ptr TypeInstance00](result.impl), gt)))
""" % [i])
output.write("")
if namespace == "Gio":
output.write(GIO_EPI)
if namespace == "Gdk":
output.write(GDK_EPI)
if namespace == "GtkSource":
output.write(GTK_SOURCE_EPI)
output.flush
var o = open("nim_gi" / (namespace.toLowerAscii) & ".nim", fmWrite)
o.write(output.data)