GUI toolkits for Nim language

Moderator: BarryK

Post Reply
User avatar
BarryK
Posts: 2738
Joined: Tue Dec 24, 2019 1:04 pm
Has thanked: 135 times
Been thanked: 745 times

GUI toolkits for Nim language

Post by BarryK »

There has already been some discussion on this topic here:

"nim hello world"
https://forum.puppylinux.com/viewtopic.php?t=6580

I have discovered 'gintro', great first impression, have posted an intro here:

"gintro GUI toolkit for Nim"
https://bkhome.org/news/202208/gintro-g ... r-nim.html

So starting a new thread to discuss this...

It is of course relevant to the pups and any Linux distro, not just EasyOS. You can obtain nim from here:

https://nim-lang.org/

User avatar
BarryK
Posts: 2738
Joined: Tue Dec 24, 2019 1:04 pm
Has thanked: 135 times
Been thanked: 745 times

Re: GUI toolkits for Nim language

Post by BarryK »

Another GUI toolkit project that is very active is 'fidget'.

The great advantage of this is that it is multiplatform. Quoting:

Fidget aims to provide performant natively compiled cross platform UIs for any platform - Web with HTML5, Windows, macOS, Linux, iOS and Android with OpenGL.

A downside is very big binary. I compiled 'demo.nim' and after stripping it is 773KB.
However, it may be a minor consideration if you want to develop a large project, say a word processor.

Very much in its favour is the ease of creating the GUI interface. The lead developer has explained in a video:

Project site:

https://github.com/treeform/fidget

Very easy to install:

Code: Select all

# nimble install fidget

If you download the 0.7.10 tagged release from github, inside is examples/demo
I created 'nim.cfg' in the demo folder:

Code: Select all

--mm:orc
--define:useMalloc
--d:release
--opt:size
--passC:"-flto"
--passL:"-flto"

Code: Select all

# nim c demo.nim
# strip demo
# ./demo
fidget-ex1.png
fidget-ex1.png (13.97 KiB) Viewed 2107 times

It is using opengl, not a native look-and-feel.

Definitely a contender for developing a largish multi-platform app.

williams2
Posts: 1062
Joined: Sat Jul 25, 2020 5:45 pm
Been thanked: 305 times

Re: GUI toolkits for Nim language

Post by williams2 »

EDIT: I see that you have already found that book. The point that a coder used to running gtkdialog from a shell script can do the exact same thing from another language, like nim or C or Bacon or python, is still valid.

If you were looking at gintro, there is a book GTK4 for Graphical User Interfaces
https://ssalewski.de/gtkprogramming.html

I think gtk2 and gtk3 would be similar, even if the details are slightly different.
(I haven't read the book, I may be wrong.)

Many languages will run a shell command as a function that returns data.
Which means you can execute gtkdialog, etc, the same as a shell script would run gtkdialog.
Which means that it's not necessary to learn new ways to create gui windows.

jeang3nie
Posts: 4
Joined: Mon Sep 26, 2022 3:47 pm

Re: GUI toolkits for Nim language

Post by jeang3nie »

I'm playing around with Gintro a bit, seeing what can be accomplished. This doesn't do much (yet), but I've managed to subclass a GtkApplicationWindow to make a composite widget, which opens up a lot of possibilities for OO type programming in Gintro. The test program is a little terminal emulator using vte.
Image

Code: Select all

# pterm.nim
import gintro/[gtk, glib, gobject, gio, vte]
import window

proc quitApp(t: Terminal, n: int, app: Application) =
    quit(app)

proc appActivate(app: Application) =
    let window = newPtermWindow(app)
    window.title = "Pterm"
    window.defaultSize = (600, 400)
    let terminal = newTerminal()
    terminal.connect("child-exited", quitApp, app)
    let environ = getEnviron()
    let command = environ.environGetenv("SHELL")
    var pid = 0
    discard terminal.spawnSync({}, nil, [command], [], {SpawnFlag.leaveDescriptorsOpen}, nil, nil, pid, nil)
    window.notebook.add(terminal)
    showAll(window)

proc main =
    let app = newApplication("org.gtk.example")
    connect(app, "activate", appActivate)
    discard run(app)

when isMainModule:
    main()

Code: Select all

# window.nim
import gintro/[gtk, gobject]

type
    PtermWindow* = ref object of ApplicationWindow
        notebook*: Notebook

when defined(gcDestructors):
    proc `=destroy`(x: var typeof(PtermWindow()[])) =
        gtk.`=destroy`(typeof(ApplicationWindow()[])(x))

proc newPtermWindow*(app: Application): PtermWindow =
    let window = newApplicationWindow(PtermWindow, app)
    let vbox = newBox(Orientation.vertical)
    window.add(vbox)
    window.notebook = newNotebook()
    vbox.packStart(window.notebook, true, true, 0)
    result = window

It would be relatively straightforward from here to make a dynamic tabbed interface, add some keybindings and have a nice little terminal emulator. Comparing to programming Gtk+ applications in either Rust or Vala (I've done both) I think the code is going to be very concise and pretty easy to follow. Much smaller executables than Rust and pretty equivalent to Vala, probably a little bigger than C (but I hate C). The big downside I see is that the documentation is horrid in comparison and the bindings aren't as mature, so there's going to be some rough edges (although it's going to be world's more flexible than using gtkdialog).

User avatar
BarryK
Posts: 2738
Joined: Tue Dec 24, 2019 1:04 pm
Has thanked: 135 times
Been thanked: 745 times

Re: GUI toolkits for Nim language

Post by BarryK »

NiGui looks quite simple, and is cross-platform:

https://github.com/simonkrauter/NiGui

A problem though, is the project, although still active, is only barely so.

I posted about the example app size in the FAQ being considerably bigger than I achieved:

https://github.com/simonkrauter/NiGui/issues/155

...the lead developer replied, but he still hasn't updated the FAQ.
Also, last commit was may 30.

jeang3nie
Posts: 4
Joined: Mon Sep 26, 2022 3:47 pm

Re: GUI toolkits for Nim language

Post by jeang3nie »

A little more progress with Gintro. I put the code I'm working on up on Codeberg.
https://codeberg.org/jeang3nie/pterm

The PtermWindow and Tab data structures are Gtk+ composite widgets. One of the benefits of doing it this way is that the parent widget can retain references to it's child widgets. For instance, the PtermWindow has a reference to it's internal Notebook, and so when a tab is removed the entire window can be passed into the closure which determines if there are any remaining tabs and if note closes the window. The Tab widget similarly gets associated with the Box, Label and Button making up it's label, so that when you press the close button on a tab that button is considered part of the tab. This is how a lot of Gtk+ programming is done in C, C++, Python etc and I wanted to see how well it translates to Nim using the bindings. It's pretty good but I'm finding a few quirks as I go along.

One little quirk is that when passing my own widgets into a callback I was getting unhelpful compile errors about the type of the data. After some head scratching I figured out that you have to cast the custom widget to it's parent class first, and then in the callback it can be cast back into it's subclass. For example when creating the "new-tab" action, it has to be called like this.

Code: Select all

discard action.connect("activate", onNewTab, Window(window))

Then when looking at the callback it then gets another cast so that any extra data associated with the subclass is available.

Code: Select all

proc onNewTab(action: SimpleAction, v: Variant, window: Window) =
    let win = PtermWindow(window)

Even with quirks I like it. I'm already up to a usable program even at 168 lines of code, which includes comments and whitespace. Next step is going to be implementing multiple terminals per tab in panes. Not sure how far I'm going to take it after that unless there's community interest.

Post Reply

Return to “EasyOS”