lets see how it looks
This commit is contained in:
parent
9db7a74aeb
commit
39930a73c9
1 changed files with 132 additions and 118 deletions
250
README.adoc
250
README.adoc
|
|
@ -8,83 +8,85 @@ Version 0.1 2017
|
|||
:icons: font
|
||||
|
||||
:GIR: GObject-Introspection
|
||||
:MAC: MacOSX
|
||||
|
||||
(c) Stefan Salewski +
|
||||
2017
|
||||
|
||||
NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf and other Nim and GTK/Gnome developers.
|
||||
The combinatorics module was kindly provided by R. Behrends.
|
||||
NOTE: This work is partly based on earlier works of _J. Mansour_ and has been supported by _A. Rumpf_ and other _Nim_ and _GTK/Gnome_ developers.
|
||||
The `combinatorics` module was kindly provided by _R. Behrends_.
|
||||
|
||||
icon:thumbs-up[] This repository contains bindings from the Nim programming language to the GTK3 GUI library and related libraries. (With minimal fixes
|
||||
it should also work for upcoming GTK4.)
|
||||
//icon:thumbs-up[]
|
||||
This repository contains bindings from the _Nim_ programming language to the _GTK3_ GUI (Graphical User Interface) library and related libraries. (With minimal fixes
|
||||
it should also work for upcoming _GTK4_.)
|
||||
|
||||
https://nim-lang.org/[Nim] is a modern universal programming language.
|
||||
|
||||
https://www.gtk.org/[GTK], also known as the Gimp Tool Kit and now sometimes also called Gnome Tool Kit, is a Graphical User Interface library.
|
||||
https://www.gtk.org/[GTK], also known as the _Gimp Tool Kit_ and now sometimes also called _Gnome Tool Kit_, is a _Graphical User Interface_ library.
|
||||
|
||||
NOTE: Later we will insert at this location a nice picture of a fancy Nim GTK3 GUI. Such a picture is fine to attract users and indeed is a good motivation.
|
||||
But such pictures are no real evidence for the quality of a GUI toolkit -- the concrete example may look nice, while the toolkit
|
||||
looks much worse in other environments and offers by far not all that what is needed in real life.
|
||||
|
||||
While GTK was initially designed and advertised as cross platform GUI toolkit, it is currently mostly used on Linux and other Unix like operation systems.
|
||||
Most Linux distributions include it, and some use it for their default desktop environment, often with the Gnome environment or other window managers.
|
||||
While GTK2 applications like GIMP are still used on Windows, there seems to exist currently only very few GTK3 applications for Windows or MacOS.
|
||||
When you develop primary free open source software for Linux or other Unix like Operating Systems, then GTK3 is a good choice for you. With some
|
||||
effort you should be even able to port your application to the proprietary Windows or MacOS operating systems. But when your primary target platforms
|
||||
are Windows and MacOS and you desire a real native look and feel there, then you may find better suited ones in the Nim software repository.
|
||||
Also, when you only need a minimal restricted GUI which is very easy to install on Windows and MacOSX, then you may find better suited packages
|
||||
in the Nim package repository. Android OS is currently not supported by GTK at all.
|
||||
While _GTK_ was initially designed and advertised as cross platform GUI toolkit, it is currently mostly used on _Linux_ and other _Unix_ like operation systems.
|
||||
Most _Linux_ distributions include it, and some use it for their default desktop environment, often with the _Gnome_ environment or other window managers.
|
||||
While _GTK2_ applications like _GIMP_ are still used on _Windows_, there seems to exist currently only very few _GTK3_ applications for _Windows_ or _{MAC}_.
|
||||
When you develop primary _free open source software_ (FOSS) for _Linux_ or other _Unix_ like operating systems, then _GTK3_ is a good choice for you. With some
|
||||
effort you should be even able to port your application to the proprietary _Windows_ or _{MAC}_ operating systems. But when your primary target platforms
|
||||
are _Windows_ and _{MAC}_ and you desire a real native look and feel there, then you may find better suited ones in the _Nim_ software repository.
|
||||
Also, when you only need a minimal restricted GUI which is very easy to install on _Windows_ and _{MAC}_, then you may find better suited packages
|
||||
in the _Nim_ package repository. _Android OS_ is currently not supported by _GTK_ at all.
|
||||
|
||||
While low level Nim bindings for GTK3 are already available since a few years, this one is an attempt to
|
||||
provide real high level bindings with full type safety, full Garbage Collector (GC) support and an idiomatic
|
||||
application interface.
|
||||
While low level _Nim_ bindings for _GTK3_ are already available since a few years, this one is an attempt to
|
||||
provide real high level bindings with full type safety, full _Garbage Collector_ (_GC_) support and an idiomatic
|
||||
_application interface_ (_API_).
|
||||
|
||||
The low level bindings available at https://github.com/ngtk3 where generated with the Nim tool c2nim directly from the C header files, are already tested
|
||||
The low level bindings available at https://github.com/ngtk3 where generated with the _Nim_ tool `c2nim` directly from the _C_ header files, are already tested
|
||||
with some applications (https://github.com/ngtk3/NEd[NEd Nim Editor], https://github.com/StefanSalewski/nim-chess3[Chess Game])
|
||||
and generally work fine. Indeed missing Garbage Collector support is generally not really a problem, as widgets are generally
|
||||
put into containers and were automatically deleted together with its parents due to GTK's reference counting.
|
||||
and generally work fine. Indeed missing _Garbage Collector_ support is generally not really a problem, as widgets are generally
|
||||
put into containers and were automatically deleted together with its parents due to _GTK_'s reference counting.
|
||||
|
||||
Still there can be some demand for really high level bindings -- so this repository tries to provide them.
|
||||
|
||||
High level GTK3 bindings, as available for many other programming languages like Python, Ruby or D already,
|
||||
High level _GTK3_ bindings, as available for many other programming languages like _Python_, _Ruby_ or _D_ already,
|
||||
would have these advantages:
|
||||
|
||||
* full Garbage Collector support -- you should never have to free resources manually
|
||||
* Widgets are Nim objects, so inheritance and sub-classing can be used
|
||||
* full _Garbage Collector_ support -- you should never have to free resources manually
|
||||
* Widgets are _Nim_ objects, so inheritance and sub-classing can be used
|
||||
* full type safety -- no needs for casts or other unsafe and dangerous operations
|
||||
|
||||
These high level bindings are based on GObject-Inrospection, an XML based database like interface description. Compared to the C header
|
||||
These high level bindings are based on _{GIR}_, an _XML_ based database like interface description. Compared to the _C_ header
|
||||
files this description gives us more and deeper information about data types and function calls, for example ownership transfer of objects and
|
||||
in or out direction of procedure variables, which makes writing the glue code much easier.
|
||||
And it should work with no or minimal
|
||||
modifications also for the upcoming GTK4.
|
||||
modifications also for the upcoming _GTK4_.
|
||||
|
||||
Unfortunately there are also some drawbacks:
|
||||
|
||||
* The Application Programmer Interface (API) will be different from what is known from C API, so using C examples or C tutorials is not really straight forward
|
||||
* The high level source code will differ from available C examples, so there would be a big demand for tutorials
|
||||
* The _Application Programmer Interface_ (API) will be different from what is known from _C API_, so using _C_ examples or _C_ tutorials is not really straight forward
|
||||
* The high level source code will differ from available _C_ examples, so there would be a big demand for tutorials
|
||||
* We need a lot of glue code, which has much room for bugs. So much testing is necessary.
|
||||
* There is some overhead due to indirect calls, leading to some code size increase and minimal
|
||||
performance loss.
|
||||
|
||||
NOTE: The new package name is "gintro", short for GObject-Introspection. The previous name was nim-gi, but the hyphen is deprecated for package names, as is the
|
||||
NOTE: The new package name is *gintro*, short for _{GIR}_. The previous name was _nim-gi_, but the hyphen is deprecated for package names, as is the
|
||||
nim prefix.
|
||||
|
||||
== Current state of these bindings
|
||||
|
||||
We are still in an early stage, but it is already more than a proof of concept. GTK and related libraries have many thousand of
|
||||
We are still in an early stage, but it is already more than a proof of concept. _GTK_ and related libraries have many thousand of
|
||||
callable functions and nearly as many data types. Testing all that is nearly impossible for a small team with limited resources.
|
||||
The initial approach was to generate low level
|
||||
bindings, which looked similar to the ones generated by the c2nim tool from the C headers. After that was done, we have associated all
|
||||
the C structs and GObject data types with Nim proxy objects. A well defined relation between these proxy object and the low level C data types
|
||||
should ensure fully automatic garbage collection. This is supported by smart type conversion, for example C strings returned by glib library
|
||||
are assigned to newly created Nim strings, while the memory of the C strings is automatically freed. For most cases this seems to work. But there
|
||||
exists a few more complicated cases, for example functions may return whole arrays of C strings or other non elementary data types,
|
||||
or function arguments or results may be so called glists,
|
||||
list structures of glib library. These cases can not be processed automatically but needs carefully manual investigations. And there may be still functions and data
|
||||
types missing: GObject Introspection query gives us many thousand lines of Nim interface code, and it is not really obvious if and what is missing.
|
||||
Some functions and data types are missing for sure -- at least some low level ones, which are considered unneeded for high level bindings by GObject-Introspection.
|
||||
But maybe more is missing, we have to investigate that. Until now these bindings have been tested only for 64 bit Linux systems with GTK 3.22.
|
||||
bindings, which looked similar to the ones generated by the `c2nim` tool from the _C_ headers. After that was done, we have associated all
|
||||
the _C_ structs and _GObject_ data types with _Nim_ proxy objects. A well defined relation between these proxy object and the low level _C_ data types
|
||||
should ensure fully automatic garbage collection. This is supported by smart type conversion, for example _C_ strings returned by `glib` library
|
||||
are assigned to newly created _Nim_ strings, while the memory of the _C_ strings is automatically freed. For most cases this seems to work. But there
|
||||
exists a few more complicated cases, for example functions may return whole arrays of _C_ strings or other non elementary data types,
|
||||
or function arguments or results may be so called _glists_,
|
||||
list structures of `glib` library. These cases can not be processed automatically but needs carefully manual investigations. And there may be still functions and data
|
||||
types missing: _{GIR}_ query gives us many thousand lines of _Nim_ interface code, and it is not really obvious if and what is missing.
|
||||
Some functions and data types are missing for sure -- at least some low level ones, which are considered unneeded for high level bindings by _{GIR}_.
|
||||
But maybe more is missing, we have to investigate that. Until now these bindings have been tested only for 64 bit _Linux_ systems with _GTK 3.22_.
|
||||
|
||||
These basic libraries are already partly tested:
|
||||
|
||||
|
|
@ -101,18 +103,18 @@ These basic libraries are already partly tested:
|
|||
* Gdk
|
||||
* Gtk
|
||||
|
||||
In best case it should be possible to add more GObject based libraries to this list without larger modifications of the generator source code.
|
||||
Unfortunately the cairo bindings provided by GObject-Introspectin are only a minimal stub -- later we will have to extend it manually.
|
||||
In best case it should be possible to add more _GObject_ based libraries to this list without larger modifications of the generator source code.
|
||||
Unfortunately the _cairo_ bindings provided by _{GIR}_ are only a minimal stub -- later we will have to extend it manually.
|
||||
|
||||
== How to try it out
|
||||
|
||||
Of course you will need a working Nim installation with a recent compiler version and you have to ensure that GTK and related libraries are installed on your system. For some Linux
|
||||
distributions which provide mainly pre-compiled software you may have to also install some GTK related developer files.
|
||||
Of course you will need a working _Nim_ installation with a recent compiler version and you have to ensure that _GTK_ and related libraries are installed on your system. For some _Linux_
|
||||
distributions which provide mainly pre-compiled software you may have to also install some _GTK_ related developer files.
|
||||
|
||||
This package now supports the nimble package manager, so ideally a plain "nimble install gintro" should do. But as this package does not
|
||||
only provide some plain text files, but uses GObject-Introspection database query on your local computer to generate
|
||||
This package now supports the _nimble package manager_, so ideally a plain `nimble install gintro` should do. But as this package does not
|
||||
only provide some plain text files, but uses _{GIR}_ database query on your local computer to generate
|
||||
binding files exactly matching your system, that does not work currently. We have to download the files, compile and execute
|
||||
the gen.nim generator program and finally to install the generates binding modules on your computer as a nimble package.
|
||||
the `gen.nim` generator program and finally to install the generated bindings modules on your computer as a _nimble package_.
|
||||
|
||||
These instructions should be enough for that:
|
||||
|
||||
|
|
@ -124,16 +126,16 @@ nimble prepare
|
|||
nimble install
|
||||
----
|
||||
|
||||
NOTE: Nimble prepare should run for about 20 seconds, it compiles and executes the generator program gen.nim.
|
||||
NOTE: Nimble prepare should run for about 20 seconds, it compiles and executes the generator program `gen.nim`.
|
||||
Unfortunately we can not guarantee that the generator command will be able to really build all the
|
||||
desired modules. The built process highly depends on your OS and installed GTK version. For 64 bit Linux systems
|
||||
with GTK 3.22 and all required dependencies installed it should work. For never GTK versions it may fail, when that GTK
|
||||
desired modules. The built process highly depends on your _OS_ and installed _GTK_ version. For 64 bit _Linux_ systems
|
||||
with _GTK 3.22_ and all required dependencies installed it should work. For never _GTK_ versions it may fail, when that _GTK_
|
||||
release introduces for example new unknown data types like array containers. In that case manual fixes may be necessary.
|
||||
The GObject Introspection based built process generates bindings customized to the OS where the generator is executed,
|
||||
so for older GTK releases or a 32 bit system different files are created. Later we may also provide pre-generated
|
||||
files for various OS and GTK versions, but building locally is preferred when possible.
|
||||
The _{GIR}_ based built process generates bindings customized to the _OS_ where the generator is executed,
|
||||
so for older _GTK_ releases or a 32 bit system different files are created. Later we may also provide pre-generated
|
||||
files for various _OS_ and _GTK_ versions, but building locally is preferred when possible.
|
||||
|
||||
Now you can built app0 and launch it:
|
||||
Now you can built `app0.nim` and launch it:
|
||||
|
||||
----
|
||||
cd /tmp/gintro/examples/
|
||||
|
|
@ -143,11 +145,11 @@ nim c app0.nim
|
|||
|
||||
== A few basic examples
|
||||
|
||||
GTK3 programs can use still the old GTK2 design, where you first initialize the GTK library, create your widgets and finally enter the GTK main loop.
|
||||
This style is still used in many tutorials as in http://zetcode.com/gui/gtk2/[Zetcode tutorial] or in the GTK book of Andrew Krause.
|
||||
Or you can use the new GTK3 App style, this is generally recommended by newer original GTK documentation.
|
||||
Unfortunately the GTK3 original documentation is mostly restricted to the GTK3 API documentation, which is generally very good, but makes
|
||||
it not very easy for beginners to start with GTK. API docs and some basic introduction is available here:
|
||||
_GTK3_ programs can use still the old _GTK2_ design, where you first initialize the _GTK_ library, create your widgets and finally enter the _GTK_ main loop.
|
||||
This style is still used in many tutorials as in http://zetcode.com/gui/gtk2/[Zetcode tutorial] or in the _GTK_ book of _A. Krause_.
|
||||
Or you can use the new _GTK3 App style_, this is generally recommended by newer original _GTK_ documentation.
|
||||
Unfortunately the _GTK3_ original documentation is mostly restricted to the _GTK3 API_ documentation, which is generally very good, but makes
|
||||
it not really easy for beginners to start with _GTK_. _API_ docs and some basic introduction is available here:
|
||||
|
||||
* https://www.gnome.org/
|
||||
* https://www.gtk.org/
|
||||
|
|
@ -156,14 +158,16 @@ it not very easy for beginners to start with GTK. API docs and some basic introd
|
|||
* https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.5
|
||||
* https://developer.gnome.org/gnome-devel-demos/stable/c.html.en
|
||||
|
||||
TIP: If you should decide to continue developing software with GTK, then you should consider installing the so called
|
||||
devhelp tool. It gives you easy and fast access to the API docs. For example, if you want to use a Button Widget in your
|
||||
GUI and wants to learn more about related functions and signals, you just enter "Button" in that tool and are guided to
|
||||
TIP: If you should decide to continue developing software with _GTK_, then you may consider installing the so called
|
||||
`devhelp` tool. It gives you easy and fast access to the _GTK API_ docs. For example, if you want to use a _Button Widget_ in your
|
||||
GUI and wants to learn more about related functions and signals, you just enter _Button_ in that tool and are guided to
|
||||
all the relevant information.
|
||||
|
||||
We start with a minimal traditional old style example, which should be familiar to most of us:
|
||||
|
||||
[[t0.nim]]
|
||||
[source,nim]
|
||||
.t0.nim
|
||||
----
|
||||
# nim c t0.nim
|
||||
import gtk
|
||||
|
|
@ -183,18 +187,20 @@ proc main =
|
|||
main()
|
||||
----
|
||||
|
||||
This is the traditional layout of GTK2 programs. When using this style then it is important to initialize the GTK library by calling gtk.init()
|
||||
at the very beginning. Then we create the desired widgets, connect signals, show all widgets and finally enter the GTK main loop
|
||||
by calling gtk.main. About connecting signals we will learn more soon, for now it is only important that we have to connect to
|
||||
This is the traditional layout of _GTK2_ programs. When using this style then it is important to initialize the _GTK_ library by calling `gtk.init()`
|
||||
at the very beginning. Then we create the desired widgets, connect signals, show all widgets and finally enter the _GTK_ main loop
|
||||
by calling `gtk.main`. About connecting signals we will learn more soon, for now it is only important that we have to connect to
|
||||
the destroy signal here to enable the user to terminate program execution by clicking the window close button.
|
||||
|
||||
Now a really minimal but complete App style example, which displays an empty window.
|
||||
Now a really minimal but complete _App style_ example, which displays an empty window.
|
||||
|
||||
NOTE: The source text of all these examples is contained in the examples directory. Unfortunately github
|
||||
NOTE: The source text of all these examples is contained in the examples directory. Unfortunately _github_
|
||||
seems to not allow to include that sources directly into this document, so there may be minimal
|
||||
differences between the source code displayed here and the sources in examples directory.
|
||||
|
||||
[[app0.nim]]
|
||||
[source,nim]
|
||||
.app0.nim
|
||||
----
|
||||
# app0.nim -- minimal application style example
|
||||
# nim c app0.nim
|
||||
|
|
@ -216,15 +222,17 @@ proc main =
|
|||
main()
|
||||
----
|
||||
|
||||
In the main proc we create a new application and connect the activate signal to our activate proc, which then creates and displays
|
||||
the still empty window. For this program we need the gtk module and also some procs and types from gio module. As both modules
|
||||
have a data type called Application (gtk extends indeed the gio.Application) we can either qualify the Application data type and its new proc
|
||||
with gtk prefix, or as we did here, exclude that from gio imports. Another solution would be to import from gio only what is really needed.
|
||||
The source code of this minimal example is stored in the examples directory, you may cd into it and type "nim c app0.nim" to create
|
||||
the executable. (Well not yet, as we provide no real nimble install. Copy app0.nim to nim_gi directory where the bindings live, or
|
||||
create symlinks for now.)
|
||||
In the `main proc` we create a new application and connect the activate signal to our `activate proc`, which then creates and displays
|
||||
the still empty window. For this program we need the `gtk` module and also some procs and data types from `gio` module. As both modules
|
||||
have a data type called `Application` (`gtk.Application` extends indeed the `gio.Application`) we can either qualify the `Application` data type and its `new proc`
|
||||
with `gtk` prefix, or as we did here, exclude that from `gio` imports. Another solution would be to import from `gio` only what is really needed.
|
||||
The source code of this minimal example is stored in the examples directory, you may `cd` into it and type `nim c app0.nim` to create
|
||||
the executable.
|
||||
|
||||
Various ways to set widget parameters are supported -- the number 1 to 6 refer to the comment below:
|
||||
//(Well not yet, as we provide no real nimble install. Copy app0.nim to nim_gi directory where the bindings live, or
|
||||
//create symlinks for now.)
|
||||
|
||||
Various ways to set widget parameters are supported -- the number 1 to 6 refer to the comments below:
|
||||
|
||||
//. Setting widget parameters
|
||||
[source,nim]
|
||||
|
|
@ -244,16 +252,18 @@ window.defaultSize = (width: 200, height: 200) # <6>
|
|||
<5> tupel assignment
|
||||
<6> tupel assignment with named members
|
||||
|
||||
Well, that empty window is really not very interesting. The GTK and Gnome team provides some GTK examples at https://developer.gnome.org/gnome-devel-demos/.
|
||||
The https://developer.gnome.org/gnome-devel-demos/3.22/c.html.en[C demos] seems to be most actual and complete, and are easy to port to Nim. So we start with these,
|
||||
but if you are familiar with the other listed languages, then you can try to port them to Nim as well. Let us start with https://developer.gnome.org/gnome-devel-demos/3.22/button.c.html.en
|
||||
Well, that empty window is really not very interesting. The _GTK_ and _Gnome_ team provides some _GTK_ examples at https://developer.gnome.org/gnome-devel-demos/.
|
||||
The https://developer.gnome.org/gnome-devel-demos/3.22/c.html.en[C demos] seems to be most actual and complete, and are easy to port to _Nim_. So we start with these,
|
||||
but if you are familiar with the other listed languages, then you can try to port them to _Nim_ as well. Let us start with https://developer.gnome.org/gnome-devel-demos/3.22/button.c.html.en
|
||||
-- it is still short and easy to understand, but shows already some interesting topics.
|
||||
|
||||
image::NimGTK3Button.png[]
|
||||
|
||||
The C code looks like this:
|
||||
The _C_ code looks like this:
|
||||
|
||||
[[button.c]]
|
||||
[source,c]
|
||||
.button.c
|
||||
----
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
|
@ -315,16 +325,18 @@ main (int argc, char **argv)
|
|||
|
||||
----
|
||||
|
||||
Converting it to Nim is straight forward with some basic C and Nim knowledge, and Nim does not force us
|
||||
to convert its shape into all the classes known from pure object orientated languages. We can either use the
|
||||
Nim tool c2nim to help us with the conversion, or do it manually. Indeed c2nim can be very helpful by
|
||||
converting C sources to Nim. Most of the time it works well. Personally I generally pre-process C files, for example
|
||||
by removing too strange macros and defines, or by replacing strange constructs, like C for loops, to simpler
|
||||
ones like while loops. Then I apply c2nim to the C file and finally manually compare the result line by line and
|
||||
fine tune the Nim code. But for this short source text we may do all that manually and finally get something like
|
||||
Converting it to _Nim_ is straight forward with some basic _C_ and _Nim_ knowledge, and _Nim_ does not force us
|
||||
to convert its shape into all the classes known from pure _Object Orientated_ (_OO_) languages. We can either use the
|
||||
_Nim_ tool `c2nim` to help us with the conversion, or do it manually. Indeed `c2nim` can be very helpful by
|
||||
converting _C_ sources to _Nim_. Most of the time it works well. Personally I generally pre-process _C_ files, for example
|
||||
by removing too strange `macros` and `defines, or by replacing strange constructs, like _C_ `for loops`, to simpler
|
||||
ones like `while loops`. Then I apply `c2nim` to the _C_ file and finally manually compare the result line by line and
|
||||
fine tune the _Nim_ code. But for this short source text we may do all that manually and finally get something like
|
||||
this:
|
||||
|
||||
[[button.nim]]
|
||||
[source,nim]
|
||||
.button.nim
|
||||
----
|
||||
# nim c button.nim
|
||||
import gtk, glib
|
||||
|
|
@ -350,30 +362,30 @@ proc main =
|
|||
main()
|
||||
----
|
||||
|
||||
Again we have the basic shape already known from app0.nim example: Main proc creates the application, connect
|
||||
to the activate signal and finally runs the application. When GTK launches the application and emits the activate signal, then
|
||||
Again we have the basic shape already known from <<app0.nim>> example: `Main proc` creates the application, connect
|
||||
to the activate signal and finally runs the application. When _GTK_ launches the application and emits the `activate` signal, then
|
||||
our activate proc is called, which creates a main window containing a button widget. That button is again connected with a
|
||||
signal, in this case named clicked. That signal is emitted by GTK whenever that button is clicked with the mouse and results
|
||||
in a call of our provided buttonClicked() proc. The procs connected to signals are called callbacks and generally got the widget
|
||||
signal, in this case named `clicked`. That signal is emitted by _GTK_ whenever that button is clicked with the mouse and results
|
||||
in a call of our provided `buttonClicked()` proc. The procs connected to signals are called _callbacks_ and generally got the widget
|
||||
on which the signal was emitted as first parameter. They can also get a second optional parameter of arbitrary type -- we will
|
||||
see that in a later example. This callback here gets only the button itself as parameter, and it's task is to reverse the
|
||||
text displayed by the button. Not very interesting basically, but we are indeed using the glib function utf8Strreverse()
|
||||
for this task. While that function internally works with cstrings, and in C we have to free the memory of the returned cstring,
|
||||
in our Nim example that is done automatically by Nim's Garbage Collector. When you compare our example carefully with the C code,
|
||||
then you may notice a difference. The C code passes the window containing the button as an additional parameter to the
|
||||
text displayed by the button. Not very interesting basically, but we are indeed using the _glib_ function `utf8Strreverse()`
|
||||
for this task. While that function internally works with `cstrings`, and in _C_ we have to free the memory of the returned `cstring`,
|
||||
in our _Nim_ example that is done automatically by _Nim_'s _Garbage Collector_. When you compare our example carefully with the _C_ code,
|
||||
then you may notice a difference. The _C_ code passes the window containing the button as an additional parameter to the
|
||||
callback function, but that parameter is not really used. We simple ignore it here, as it is not used at all.
|
||||
//and I assume that passing a widget in this way in our nim code
|
||||
//may not work already currently. Fortunately widgets as optional parameter are not often needed, and we will try to make that
|
||||
//working soon...
|
||||
In one of the following examples you will learn how passing (nearly) arbitrary parameters in a type safe way is done.
|
||||
Another difference is, that the C code returns an integer status value returned by g_application_run() to the OS. We
|
||||
could do the same by using the quit() proc of Nim's OS module, but as that would give us no additional benefit, we simply ignore it.
|
||||
Another difference is, that the _C_ code returns an `integer` status value returned by `g_application_run()` to the _OS_. We
|
||||
could do the same by using the `quit() proc` of _Nim_'s _OS_ module, but as that would give us no additional benefit, we simply ignore it.
|
||||
|
||||
TIP: The command nim c sourcetext.nim generates an executable which contains code for runtime checks and debugging,
|
||||
TIP: The command `nim c sourcetext.nim` generates an executable which contains code for runtime checks and debugging,
|
||||
which increases executable size and decreases performance.
|
||||
After you have tested your software carefully, you may give the additional parameter -d:release to avoid this. For the gcc backend
|
||||
you may additional enable link time optimization (LTO), which reduces executable size further. To enable LTO. you may put
|
||||
a nim.cfg file in your sources directory with content like
|
||||
After you have tested your software carefully, you may give the additional parameter `-d:release` to avoid this. For the `gcc` backend
|
||||
you may additional enable _link time optimization_ (_LTO_), which reduces executable size further. To enable _LTO_ you may put
|
||||
a `nim.cfg` file in your sources directory with content like
|
||||
|
||||
----
|
||||
path:"$projectdir"
|
||||
|
|
@ -381,21 +393,23 @@ nimcache:"/tmp/$projectdir"
|
|||
gcc.options.speed = "-march=native -O3 -flto -fstrict-aliasing"
|
||||
----
|
||||
|
||||
With that optimization, your executable sizes should be in the range of about 50 kilobyte only!
|
||||
With that optimization, your executable sizes should be in the range of about 50 _kB_ only!
|
||||
|
||||
=== Optional, type safe parameters for callbacks
|
||||
|
||||
The next example shows, how we can pass (nearly) arbitrary parameters to our connect procs.
|
||||
We pass a string, an object from the stack, a reference to an object allocated on the heap
|
||||
and finally a widget (in this case the application window itself, you may also try passing
|
||||
another button). As the main window itself is a so called GTK bin and can contain only one
|
||||
child widget, we create a container widget, a vertical box in this case, fill that box with
|
||||
some buttons, and add that button to the window.
|
||||
another button). As the main window itself is a so called _GTK_ `bin` and can contain only one
|
||||
single child widget, we create a container widget, a vertical box in this case, fill that box with
|
||||
some buttons, and add that box to the window.
|
||||
|
||||
Compile and start this example from the command line and watch what
|
||||
happens when you click on the buttons.
|
||||
|
||||
[[connect_args.nim]]
|
||||
[source,nim]
|
||||
.connect_args.nim
|
||||
----
|
||||
# nim c connect_args.nim
|
||||
import gtk, glib
|
||||
|
|
@ -454,7 +468,7 @@ main()
|
|||
|
||||
To prove type safety, we may modify one of the callback procs and watch the compiler output:
|
||||
|
||||
[source,c]
|
||||
[source,nim]
|
||||
----
|
||||
proc b1Callback(button: Button; str: int) =
|
||||
discard # echo str
|
||||
|
|
@ -470,30 +484,30 @@ proc b1Callback(button: Button; str: int)
|
|||
It may be not always really obvious what the compiler wants to tell us, but at least we
|
||||
are told that it got a string and expected an int.
|
||||
|
||||
Currently the connect function is realized by a Nim type safe macro. Connect accepts two or three
|
||||
Currently the connect function is realized by a _Nim_ type safe `macro`. Connect accepts two or three
|
||||
arguments -- the widget, the signal name and the optional argument. When the optional argument
|
||||
is a ref (reference to objects on the heap) then it is passed as a reference, otherwise a deep copy
|
||||
of the argument is passed. For the above code this means, that r and the window are passed
|
||||
of the argument is passed. For the above code this means, that `r` and the `window` variables are passed
|
||||
as references, while the string and the stack object are deep copied. Currently it is not possible
|
||||
to release the memory of passed arguments again. This should be no real problem, as in most
|
||||
cases no arguments are passed at all, and when arguments are passed, then they are general
|
||||
small in size like plain numbers or strings, or maybe references to widgets which could not be freed
|
||||
at all, as they are part of the GUI. Later we may add more variants of that connect macro.
|
||||
at all, as they are part of the _GUI_. Later we may add more variants of that connect macro.
|
||||
|
||||
NOTE: Navigation can be hard for beginners. You may have basic knowledge of GTK and want
|
||||
to build a GUI for your application. But how to find what you need. Well, we offer no separate
|
||||
automatically generated API documentation currently, as that is not really helpful. In most cases
|
||||
it is easy to just guess Nim symbol names, proc parameters and all that. Using a smart editor
|
||||
with good nimsuggest support further supports navigation -- for example NEd shows us
|
||||
all the needed proc parameters when we move the cursor on a proc name, or we press CTRL-W and jump
|
||||
to the definition of that symbol. For unknown stuff the original C function name is often a good starting point.
|
||||
Assume you don't know much about GTK's buttons, but you know that you want to have a Button in
|
||||
your GUI application. GTK generally offers generator functions containing the string "new" in their name.
|
||||
So it is easy to guess that there exists a C function named "gtk_button_new". That name is also
|
||||
contained in the bindings files, in this case in gtk.nim. So we open that file in a text editor and search for
|
||||
NOTE: Navigation can be hard for beginners. You may have basic knowledge of _GTK_ and want
|
||||
to build a _GUI_ for your application. But how to find what you need. Well, we offer no separate
|
||||
automatically generated _API_ documentation currently, as that is not really helpful. In most cases
|
||||
it is easy to just guess _Nim_ symbol names, proc parameters and all that. Using a smart editor
|
||||
with good `nimsuggest` support further supports navigation -- for example `NEd` shows us
|
||||
all the needed proc parameters when we move the cursor on a proc name, or we press kbd:[Ctrl+W] and jump
|
||||
to the definition of that symbol. For unknown stuff the original _C_ function name is often a good starting point.
|
||||
Assume you don't know much about _GTK_'s buttons, but you know that you want to have a button in
|
||||
your _GUI_ application. _GTK_ generally offers generator functions containing the string `new` in their name.
|
||||
So it is easy to guess that there exists a _C_ function named `gtk_button_new`. That name is also
|
||||
contained in the bindings files, in this case in `gtk.nim`. So we open that file in a text editor and search for
|
||||
that term. So it is really easy to find first starting points for related procs and data types. Most data types
|
||||
are located near by their related functions, so you should be able to find all relevant information fast.
|
||||
Remember the GTK devhelp tool, and use also grep or the nim-grep variant.
|
||||
Remember the _GTK_ `devhelp` tool, and use also `grep` or the `nimgrep` variant.
|
||||
|
||||
NOTE: Related work: https://github.com/jdmansour/nim-smartgi
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue