GithubHelp home page GithubHelp logo

can-lehmann / owlkettle Goto Github PK

View Code? Open in Web Editor NEW
359.0 10.0 14.0 5.8 MB

A declarative user interface framework based on GTK 4

Home Page: https://can-lehmann.github.io/owlkettle/README

License: MIT License

Nim 100.00%
nim gtk user-interface framework declarative ui declarative-ui gui gtk4

owlkettle's Introduction

Owlkettle

Freshly brewed user interfaces.

Owlkettle is a declarative user interface framework based on GTK. It is written in Nim.

Here is an example for a simple counter app. When you click on the "+" Button, the counter increments.

import owlkettle

viewable App:
  counter: int

method view(app: AppState): Widget =
  result = gui:
    Window:
      title = "Counter"
      defaultSize = (200, 60)

      Box(orient = OrientX, margin = 12, spacing = 6):
        Label(text = $app.counter)
        Button {.expand: false.}:
          text = "+"
          style = [ButtonSuggested]
          proc clicked() =
            app.counter += 1

brew(gui(App()))

The code above will result in the following application:

Counter Application

Owlkettle also supports building libadwaita apps. To enable libadwaita, import owlkettle/adw and change the last line to adw.brew(gui(App())).

Counter Application using Adwaita Stylesheet

Installation

Owlkettle requires GTK 4 to be installed on your system. You can install it by running:

  • dnf install gtk4-devel libadwaita-devel on Fedora
  • apt install libgtk-4-dev libadwaita-1-dev on Ubuntu
  • pacman -S mingw-w64-x86_64-gtk4 mingw-w64-x86_64-libadwaita on Windows' MSYS2
$ nimble install owlkettle

Check out the installation guide for further instructions.

Documentation

You can find a reference of all widgets in docs/widgets.md.

A tutorial for building a simple Todo application can be found here.

Additional examples can be found here.

A reference of all supported libadwaita widgets can be found in docs/widgets_adwaita.md.

License

Owlkettle is licensed under the MIT license. See LICENSE.txt for more information.

owlkettle's People

Contributors

aleksrutins avatar beef331 avatar can-lehmann avatar ire4ever1190 avatar jiro4989 avatar nylki avatar philippmdoerner avatar planetis-m avatar rickbarretto avatar sirolaf avatar solitudesf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

owlkettle's Issues

Spurious error when using iterator with static parameter.

When using an iterator that uses a static parameter for the return type as following the DSL causes an error:

import owlkettle

type
  Thing = enum
    a, b, c
  MyType[T: static Thing] = object

iterator doThing(val: static Thing): MyType[val] = yield MyType[val]()

viewable App:
  a: int

method view(app: AppState): Widget =
  result = gui:
    Window:
      title = "Counter"
      defaultSize = (200, 60)
      Box():
        for val in doThing(a):
          Label(text = "hello")

brew(gui(App()))

/home/jason/.nimble/pkgs/owlkettle-#head/owlkettle/guidsl.nim(189, 23) Error: A nested proc can have generic parameters only when it is used as an operand to another routine and the types of the generic paramers can be inferred from the expected signature.

This might be resolved in closure generation by wrapping with when ident isnot static: var ident = ident. Or if the code is typed checking if the symKind is a var/let instead of just using all syms.

Is it sensible to add GTK doc-links to bindings of GTK-things?

This one occurred to me while I was googling gtk docs to see the docs for g_object_unref to see if there's more info on it (and to realize that this is used for gtk's own version of ARC or sth):

Would it make sense to add GTK doc links (such as: https://docs.gtk.org/gobject/method.Object.ref.html) to the gtk.nim module?
I thought it might be nice because I very often can't be 100% certain that I'll actually find what I google for, particularly if it's something more hidden in the docs. So having a direct link helps me and simplifies things - though I don't know any of that applies to any of the things bound in gtk.nim.

I don't expect you to do it, this is a thing I'm happy to do over time as I have to deal with this (or when I have a calm couple hours and am mentally braindead, the perfect state to do something like this in).

I'm mostly asking if you think this would provide value. I guess the majority of that would come if we also ran nim docs over the library to create a API index docs?

Or would it be mostly pointless?

Add support for setting custom css classes

Wanted to add this issue mostly so we don't forget about it and because it's personally important to me.

Currently, there is no official way to set a custom CSS class to a widget, which you could style as you'd want.

There is an unofficial hacky way that we talked about (documented here for any future reader) - Use the afterBuild hook :

import owlkettle, owlkettle/gtk

viewable RedCounterButton:
  count: int = 0
  
  hooks:
    afterBuild:
      let
        internalWidget = state.unwrapInternalWidget()
        styleContext = gtk_widget_get_style_context(internalWidget)
      gtk_style_context_add_class(styleContext, "red-background")

method view(state: RedCounterButtonState): Widget =
  result = gui:
    Button:
      text = $state.count
      proc clicked() =
        state.count += 1

viewable App:
  discard

method view(app: AppState): Widget =
  result = gui:
    Window:
      RedCounterButton()

brew(gui(App()), stylesheets=["stylesheet.css"])

And in stylesheet.css:

.red-background {
  background: #ff0000;
}

(This only works with the current head commit, current being 25.02.2023, for anyone trying to do this).

I'm honestly not sure how a "proper" solution would be implemented. Should we have some kind of static "cssClass" field on WidgetState that is assumed to be there and whose value gets transferred to the internal-widget during the build and update phases after the hooks have run?

MenuButton causes gtk error only in f38

i have a HeaderBar with a viewable in it that contains a MenuButton. It works fine in fedora 37 and ubuntu 22.04.1, but causes the below gtk error when clicking on it in fedora 38.

Gtk-CRITICAL **: 06:39:43.725: _gtk_css_corner_value_get_x: assertion 'corner->class == &GTK_CSS_VALUE_CORNER' failed

thanks

Example: Todo app Error - UPDATE all examples error out.

Nim Version = 1.6.6 Stable

Error: Undeclared field: 'has_margine'

When running example todo.nim

nim c -r todo.nim Hint: used config file '/home/nixfreak/.choosenim/toolchains/nim-#devel/config/nim.cfg' [Conf]
Hint: used config file '/home/nixfreak/.choosenim/toolchains/nim-#devel/config/config.nims' [Conf]
...............................................................................................
/home/nixfreak/.nimble/pkgs/owlkettle-1.3.0/owlkettle/widgetdef.nim(510, 6) Hint: 'gen_docs' is declared but not used [XDeclaredButNotUsed]
.......
/home/nixfreak/.nimble/pkgs/owlkettle-1.3.0/owlkettle.nim(35, 24) Hint: conversion from WidgetState to itself is pointless [ConvFromXtoItselfNotNeeded]
/home/nixfreak/.nimble/pkgs/owlkettle-1.3.0/owlkettle.nim(68, 7) Hint: 'status' is declared but not used [XDeclaredButNotUsed]
/home/nixfreak/nim/gui/owlkettle/examples/todo.nim(35, 12) template/generic instantiation of gui from here
/home/nixfreak/.nimble/pkgs/owlkettle-1.3.0/owlkettle/guidsl.nim(197, 22) Error: undeclared field: 'has_margin' for type widgets.Box [type declared in /home/nixfreak/.nimble/pkgs/owlkettle-1.3.0/owlkettle/widgetdef.nim(243, 10)]

UPDATE:: All examples have giving the same error.

Warning: 'Lock levels' are deprecated, now a noop [Deprecated]

Apparently with nim 2.0 lock levels were done away with.
Where previously we had {.locks: 0.} to signify that this code would never acquire a lock, we now don't.

According to Rika on the discord it should be fine to just remove those as they shouldn't be needed anymore, but I'm not insanely sure on that.
There appears to be no new way at least to express "This code should never acquire a lock" (At least I think that:s what locks:0 expressed).

I opened a forum thread to ask about this topic: https://forum.nim-lang.org/t/10487#69953

The "development" for this ticket is a pretty simple Find-replace of locks: 0 with either nothing or whatever the solution is.

How to work with key press events

Hi,
I followed the tutorial to get started with Owlkettle and created the ToDo application. Now I wonder if I could bind the 'Enter' key of my keyboard to have the same effect as clicking the '+' button. Is this possible in the current version or is this planned for the future? Maybe I overlooked something in the docs / tutorial.
Thanks you in advance.

Add renderable Gtk.Grid widget to owlkettle widgets

Currently there is no way to specify a grid-layout. You can emulate one by using the various Box-widgets, or write a custom renderable wrapper of Gtk.Grid yourself in your own application.

It would be beneficial for owlkettle to include its own renderable of Gtk.Grid for that purpose.

Cannot limit height of elements

Playing around making a launcher, and it seems individual elements cannot have limited height (I could be wrong). This results in very unusable UI

image

Update `=destroy` hooks

With Nim 2.0.0, the function signature for =destroy hooks changed.
These need to be updated, the compiler warnings should tell you the relevant locations.

Grid causes segfaults when updating the state after an event

Description

When rendering a grid with a checkbox in it and then clicking on the checkbox, you get a segfault

Minimal example:

  1. Run this:
import owlkettle

viewable App:
  discard

method view(app: AppState): Widget =

  result = gui:
    Window():
      Grid():
        CheckButton() {.x: 2, y:5.}:
          state = true
          proc changed(state: bool) =
            echo "Potato"

brew(gui(App()))
  1. click on the checkbox

Stacktrace

Traceback (most recent call last)
/home/philipp/dev/playground/src/playground.nim(16) playground
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle.nim(180) brew
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/mainloop.nim(55) runMainloop
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgets.nim(1488) toggledCallback
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetutils.nim(31) redraw
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetdef.nim(79) redraw
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetdef.nim(52) update
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetdef.nim(525) update
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgets.nim(149) updateState
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetutils.nim(112) updateChild
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetutils.nim(84) updateChild
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetdef.nim(52) update
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetdef.nim(525) update
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgets.nim(2318) updateState
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgets.nim(2264) attach
/home/philipp/.nimble/pkgs/owlkettle-#head/owlkettle/widgetdef.nim(73) unwrapInternalWidget
SIGSEGV: Illegal storage access. (Attempt to read from nil?)

Further information

The last 2 procs that are being called are:

proc attach(grid: GtkWidget, child: GridChild[WidgetState]) =
  gtk_grid_attach(grid,
    child.widget.unwrapInternalWidget(),
    child.region.x.cint,
    child.region.y.cint,
    child.region.width.cint,
    child.region.height.cint
  )

which calls

proc unwrapInternalWidget*(state: WidgetState): GtkWidget =
  result = state.unwrapRenderable().internalWidget

It appears that the state has become nil and "unwrapRenderable()" deals with that by also responding with nil have become nil somehow during the update-cycle (?).

With a modified "unwrapInternalWidget" proc :

proc unwrapInternalWidget*(state: WidgetState): GtkWidget =
  echo "A"
  echo state == nil
  echo "B"
  echo state.unwrapRenderable() == nil
  echo "C"
  result = state.unwrapRenderable().internalWidget
  echo "D"

You will get these results when running and then clicking the checkbox

A
false
B
false
C
D
A
false
B
false
C
D
A
false
B
false
C
D
A
false
B
false
C
D
------ CLICK -------
Potato
A
false
B
false
C
D
A
true
B
true
C

Why am I assuming this is heavily Grid related? If you try this with box it will work as expected:

import owlkettle

viewable App:
  discard

method view(app: AppState): Widget =

  result = gui:
    Window():
      Box():
        CheckButton():
          state = true
          proc changed(state: bool) =
            echo "Potato"

brew(gui(App()))

Temperature converter ex: negative values

Just tested some examples for the first time today.
There is a funny thing about the temperature converter : it accepts mathematical expressions (-,+,*,/ but probably not ^ unless imported with std/math).

Yet, it does not accept any negative number in the celsius field at least.
But it converts without problem if 0.0-1.0 is given.

As a side not too, "1.0/" in the Celsius Field gives "inf" in the Farenheit field while I suppose it should tell it is an invalid value instead.

These are not really bug/limitations of the owlkettle library, but of the demo itself.
Feel free to close this "issue", since I guess bugs in the library are more important than bugs in the demos.

What broke the deployment pipeline for nimibook-docs?

Discussed in #74

Originally posted by PhilippMDoerner September 13, 2023
As you may have guessed from discord, the nimibook-docs for a while didn't have some of the nim-files.
I saw you updating the pipeline to nim 2.0.0 but I don't quite get how that lead to some of the pages not getting compiled/served on github pages.

Do you have any deeper insight?

According to investigations by @PhilippMDoerner, the try/except statement on line 42 of the nimble file may be at fault, for not showing that the docs failed to build.

Add mention of gtk4-icon-browser for figuring out available icons to docs

First up, thanks for making the library! I'm new to GUI toolkits like GTK/QT (originally webdev) and I've been playing around with this for a couple hours and had quite a bit of fun with how quickly and easily everything fit together, particularly how easy it was to split Widgets into their own files and have them share data!

I was fiddling around with the todo-list tutorial and I noticed it using a couple icons here or there. That got me wondering what the available icons were. After 15 minutes of googling and some luck I stumbled over a mention of gtk4-icon-browser. A bit of more googling later on how to install that and I had a chance to see what icons there are. It would be nice if we could shorten that link from "Oh, what icons can I have?" to finding that list for newcomers such as myself.

Imo it makes sense to mention in the docs what tooling there is out there that one likely needs, such as gtk4-icon-browser to see a list of available icons. If there are more things out there that one should know about I'd love to of course also know about those ^^

I'd be happy to write a 3-4 line paragraph for this, but I'm not sure where this should be mentioned. A separate "recommended-tools.md" ? As part of "widgets.md" at the bottom?

SIGSEGV with ListBox under some circumstances

Here's a simple program:

import std/sets
import owlkettle

viewable App:
  rows: seq[string] = @["one", "two", "three"]

method view(app: AppState): Widget =
  gui:
    Window:
      ListBox:
        selectionMode = SelectionSingle

        proc select(pages: HashSet[int]) =
          discard

        for r in app.rows:
          Label:
            text = r
            xAlign = 0
            margin = 5

brew(gui(App()))

When closing the window it crashes with SIGSEGV

Traceback (most recent call last)
/home/dawid/scratch/nim_stuff/simple_gtk/list_box.nim(22) list_box
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle.nim(180) brew
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/mainloop.nim(55) runMainloop
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgets.nim(2015) selectedRowsChanged
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetutils.nim(30) redraw
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(79) redraw
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(52) update
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(525) update
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgets.nim(121) updateState
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetutils.nim(111) updateChild
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetutils.nim(83) updateChild
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(52) update
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(525) update
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgets.nim(2023) updateState
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetutils.nim(160) updateChildren
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(52) update
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(525) update
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgets.nim(1969) updateState
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetutils.nim(111) updateChild
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetutils.nim(83) updateChild
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(52) update
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgetdef.nim(525) update
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgets.nim(353) updateState
/home/dawid/.asdf/installs/nim/1.6.12/nimble/pkgs/owlkettle-2.2.0/owlkettle/widgets.nim(59) updateState
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
fish: Job 1, './list_box' terminated by signal SIGSEGV (Address boundary error)

Commenting out either select proc or margin from label widget fixes the issue.

ListBoxRow cannot easily be interacted with keyboard.

Using the arrow keys to navigate the following program the selection moves to the box, but it requires tab to move to the button then enter to interact with it.

import owlkettle

viewable App: discard

method view(app: AppState): Widget =
  result = gui:
    Window:
      default_size = (600, 400)
      proc close() = quit(1)
      ScrolledWindow:
        ListBox:
          for i in 0..10:
            ListBoxRow:
              Button:
                text = $i
                proc clicked() = echo i


brew(gui(App()))

[FR] Add Gtk.ColumnView to owlkettle widgets

It seems that Gtk.ColumnView is the widget i need for the application i'm currently building, and future similar applications.

I need to list a seq of objects in horizontal rows with each object field's data in a column with a header, and i need sorting and eventually filtering. It sounds like this is what ColumnView was made for.

thanks

Passing viewables between windows

I would like to understand better viewables.
I am developing a game in which a new window enable to select the parameters for a new game. The game itself occurs in the main initial window.

I would like to change the parameters of the viewable used by the main window. The only approach I found was to use a global variable.
Can we avoid a global variable and pass new parameters when opening or quitting a window? Below is a minimal example similar to what I have:

import owlkettle, sequtils

var counter: int = 0

viewable App:
  counter: int = 0

viewable ChangeCounter:
  selected: int = 0
  items: seq[string] = mapIt(0..<100, "Option " & $it)

method view(app: ChangeCounterState): Widget =
    result = gui:
        Window:
            title = "Change Counter"
            defaultSize = (200, 60)
            Box(orient = OrientY, spacing = 6, margin = 12):
                Box(spacing = 6) {.expand: false.}:
                    Label:
                        text = "Drop Down"
                        xAlign = 0
                        
                    DropDown {.expand: false.}:
                        items = app.items
                        selected = app.selected
                        proc select(item: int) =
                            app.selected = item
                            counter = app.selected
                    
                    Button {.expand: false.}:
                        text = "OK"
                        style = [ButtonSuggested]
                        proc clicked() =
                            app.closeWindow()

method view(app: AppState): Widget =
  result = gui:
    Window:
      title = "Counter"
      defaultSize = (200, 60)
      Box(orient=OrientY, spacing=12):
        Button {.expand: false.}:
          text = "-"
          proc clicked() =
            app.counter -= 1
        Label(text = $app.counter)
        Button {.expand: false.}:
          text = "+"
          style = [ButtonSuggested]
          proc clicked() =
            app.counter += 1

      HeaderBar {.addTitlebar.}:               
        Button {.addRight.}:
          text = "Counter Value"
          style = [ButtonSuggested]
          proc clicked() =
            discard app.open: gui:
              ChangeCounter()
            app.counter = counter

brew(gui(App()))

The main window has a counter which can be updated (extracted from the counter.nim example).
The second window enables to select a specific value for the counter. For this I use the global variable counter. When I quit the second window, I update the application counter with the value of the global variable.

Can I avoid the use of the global variable?

[FR] enable hasStyle= for MessageDialog/BuiltInDialog

I'm using MessageDialog as error message dialog for FileChooserDialog error. Would like to be able to style the text. It's currently pretty hard to even see the MessageDialog over the normal app window, at least with dark DE theme. Not super readable either.

thanks

Gtk.Switch buggy in f38

hi,
An application i built [1] uses a Gtk.Switch and it's very buggy[2] in fedora 38, but works perfectly fine in f37 and ubuntu 22.04.1. I even built the binary in each OS for max compat. Do you think this might be an owlkettle issue, or i should report upstream?

thanks

f37 gtk: 4.8.3-1
ubuntu 22.04.1 gtk: 4.6.9
f38 gtk: 4.10.4-1

  1. My app's repo is not public yet, but i can provide src code or access to the private repo for you. Will be public and gpl3 when it's little website is done, and preferably f38 (newer gtk) supported.
  2. doesn't always change when clicked, or changes the switch background color and position of slider, but other parts of my gui that depend on the state change don't update, or changes background color, but doesn't move slider, and variations of these.

[QoL - FeatureRequest] provide a compiler-flag that automatically draws colorful borders around all Widgets

I stumbled over this while developing. Relatively often I have situations where I'm getting spacing between elements due to Box using AlignFill by default. That is generally a sensible default, but it also makes it that I often have to guess why elements are spaced as far apart as they are, e.g. here:

image

I don't immediately have any configs that push a 40pt or however large margin between "License: MIT" and "Dependencies".
It would be immensely helpful if during development I had an option that would show me the borders of all the various elements without me having to manually add them everywhere.

Bonus points if somehow the name of the Viewable-Widget could be displayed when my mouse hovers over it.
Though maybe if we can do that, we could add additional information like Margin, expand, vAlign/hAlign etc.

Feature questions

Forgive me if any of these exist here already:

  • automatic text wrapping*
  • font size (and outline?), % growth option for text and icons (especially in buttons)
  • traditional menu bar. Also detecting what is being used (like Gnome vs other DEs or whenever using no-CSD)
  • tray menu. (or maybe that'd be a different package)

*=this is actually the most important one for me now, because I wanted attempt to make a digital choose-your-adventure system.

How do I move focus from one widget to another?

Hi!
In the example TODO app after pressing the + button I want to move focus back to the entry widget.
How can I do that?
I guess I have to use gtk_widget_grab_focus, but how do I get reference to entry widget?

file_dialog segfault

$ ./file_dialog 

(file_dialog:82643): Gtk-WARNING **: 22:11:41.653: Theme parsing error: gtk-contained-dark.css:2871:228: Missing closing bracket for :not()

(file_dialog:82643): Gtk-WARNING **: 22:11:43.383: Invalid input string

(file_dialog:82643): Gtk-WARNING **: 22:11:43.383: Invalid input string

(file_dialog:82643): Gtk-WARNING **: 22:11:43.383: Invalid input string

(file_dialog:82643): Gtk-WARNING **: 22:11:43.383: Invalid input string
Traceback (most recent call last)
/tmp/owlkettle/examples/file_dialog.nim(59) file_dialog
/home/user/.nimble/pkgs/owlkettle-1.5.0/owlkettle.nim(72) brew
/home/user/.nimble/pkgs/owlkettle-1.5.0/owlkettle/widgets.nim(32) event_callback
/tmp/owlkettle/examples/file_dialog.nim(40) :anonymous
/home/user/.nimble/pkgs/owlkettle-1.5.0/owlkettle.nim(35) open
/home/user/.nimble/pkgs/owlkettle-1.5.0/owlkettle/widgetdef.nim(48) build
/home/user/.nimble/pkgs/owlkettle-1.5.0/owlkettle/widgets.nim(1369) build
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Segmentation fault (core dumped)

archlinux
Nim Compiler Version 1.6.6
to reproduce just click "Open" button

Macros `echo result.repr`

I was going to make a PR to fix this but given that you have it in multiple positions I feel like you desire this behaviour. If so can it be moved behind a owlkettleDebug flag to not pollute the terminal on project build?

Type mismatch error for `ContextMenu.updateChild`

Heyho, on the current head commit I get the following error when compiling:

Error: type mismatch: got <ContextMenuState, WidgetState, Widget, proc (box: GtkWidget, oldMenu: GtkWidget, newMenu: GtkWidget){.closure, noSideEffect, gcsafe, locks: <unknown>.}>
but expected one of:
proc updateChild(state: Renderable; child: var BoxChild[WidgetState];
                 updater: BoxChild[Widget];
                 setChild: proc (widget, child: GtkWidget) {.cdecl, locks: 0.})
  first type mismatch at position: 2
  required type for child: var BoxChild[widgetdef.WidgetState]
  but expression 'state.menu' is of type: WidgetState
proc updateChild(state: Renderable; child: var WidgetState; updater: Widget;
                 addChild: proc (widget, child: GtkWidget) {.cdecl, locks: 0.};
    removeChild: proc (widget, child: GtkWidget) {.cdecl, locks: 0.})
  first type mismatch at position: 4
  required type for addChild: proc (widget: GtkWidget, child: GtkWidget){.cdecl, locks: 0.}
  but expression 'replace' is of type: proc (box: GtkWidget, oldMenu: GtkWidget, newMenu: GtkWidget){.closure, noSideEffect, gcsafe, locks: <unknown>.}
  Calling convention mismatch: got '{.closure.}', but expected '{.cdecl.}'.
  Pragma mismatch: got '{.locks: <unknown>.}', but expected '{.locks: 0.}'.
  The `.locks` requirements differ. Annotate the proc with {.locks: 0.} to get extended error information.
proc updateChild(state: Renderable; child: var WidgetState; updater: Widget;
                 setChild: proc (widget, child: GtkWidget) {.cdecl, locks: 0.})
  first type mismatch at position: 4
  required type for setChild: proc (widget: GtkWidget, child: GtkWidget){.cdecl, locks: 0.}
  but expression 'replace' is of type: proc (box: GtkWidget, oldMenu: GtkWidget, newMenu: GtkWidget){.closure, noSideEffect, gcsafe, locks: <unknown>.}
  Calling convention mismatch: got '{.closure.}', but expected '{.cdecl.}'.
  Pragma mismatch: got '{.locks: <unknown>.}', but expected '{.locks: 0.}'.
  The `.locks` requirements differ. Annotate the proc with {.locks: 0.} to get extended error information.
proc updateChild(state: Renderable; child: var WidgetState; updater: Widget;
    replaceChild: proc (widget, oldChild, newChild: GtkWidget) {.locks: 0.})
  first type mismatch at position: 4
  required type for replaceChild: proc (widget: GtkWidget, oldChild: GtkWidget, newChild: GtkWidget){.closure, locks: 0.}
  but expression 'replace' is of type: proc (box: GtkWidget, oldMenu: GtkWidget, newMenu: GtkWidget){.closure, noSideEffect, gcsafe, locks: <unknown>.}
  Pragma mismatch: got '{.locks: <unknown>.}', but expected '{.locks: 0.}'.
  The `.locks` requirements differ. Annotate the proc with {.locks: 0.} to get extended error information.

expression: updateChild(state, state.menu, widget.valMenu, replace)

 *  The terminal process "/usr/bin/zsh '-c', 'nim c --define:ssl --mm:refc --panics:on --run --styleCheck:usages --spellSuggest:50 src/nimblest.nim'" terminated with exit code: 1. 

This refers to widgets.nim line 2053, which makes use of a replace proc whose lock-level doesn't quite work.

The following change fixes the compilation issue (Line 2023):
From:
proc replace(box, oldMenu, newMenu: GtkWidget)
To:
proc replace(box, oldMenu, newMenu: GtkWidget) {.locks: 0.}=

This is with the compile command nim c --define:ssl --mm:refc --panics:on --run --styleCheck:usages --spellSuggest:50 src/nimblest.nim

Nim version:

Nim Compiler Version 1.6.10 [Linux: amd64]
Compiled at 2022-11-21
Copyright (c) 2006-2021 by Andreas Rumpf

git hash: f1519259f85cbdf2d5ff617c6a5534fcd2ff6942
active boot switches: -d:release

Not quite sure what's going on there? Is this a refc issue?

Add links to gtk docs for enums (or other things where that might be useful)

Heyho!
Similar to #26 I stumbled over something that I thought might facilitate "finding" something. I wanted to select a "SelectionMode" for ListBox and had no idea what SelectionBrowse was and couldn't differentiate it at a glance from SelectionSingle.

On the assumption that this was gtk stuff with a bit of googling and clicking around the ListBox docs I finally found https://docs.gtk.org/gtk4/enum.SelectionMode.html . I think it could make sense to add these links to the Widget documentation. Similarly as per #26 I'd be happy to do a PR to add those as I stumble over them, assuming that is desired.

[FR] add supported nim version, compiler options to readme

It would be nice if the nim version owlkettle is being tested with, as well as compiler options used, were documented in the readme. I just tried compiling with nim-1.6.12 and orc and i'm getting errors like:

/home/itwrx/.cache/nim/muhapp_d/@mviews@sroutine_list.nim.c:3049:17: error: โ€˜colontmpD_โ€™ undeclared (first use in this function)
 3049 |                 colontmpD_ = (*((void**) (stateX60gensym3_)));

and:

/home/itwrx/.cache/nim/muhapp_d/@m..@s..@s..@s..@[email protected]@spkgs@sowlkettle-@hhead@[email protected]:26721:17: error: โ€˜colontmpD_โ€™ undeclared (first use in this function)
26721 |                 colontmpD_ = (*((void**) (stateX60gensym1_)));

compiling with refc, boehm, markAndSweep, and go works.

thanks

Support a `clean` target in the make file

Disclaimer: I have 0 clue of make files. Honestly, using them here has been the largest exposure I've had to them thus far.

Background:

Github pipelines are behaving super weird (namely the doc-deployment-pipeline I want to introduce as part of the latest PR). See for example this job:

https://github.com/PhilippMDoerner/owlkettle/actions/runs/4260144430

For this commit:

PhilippMDoerner@dda9e2d

The commit does not contain any changes that are relevant to the nimble genDocs command (which just runs make -C docs ). Yet the pipeline occasionally just randomly fails for not understandable reasons. The linked action for example did fail with that error, but ran perfectly fine after rerunning it with debug logging enabled (here a link to one that failed repeatedly even after rerunning). Generally the error is this message:

/usr/bin/ld: /home/runner/.cache/nim/adw_d/@madw.nim.c.o: in function `buildState__adw_998':
@madw.nim.c:(.text+0x67d5): undefined reference to `adw_entry_row_remove'
/usr/bin/ld: @madw.nim.c:(.text+0x67df): undefined reference to `adw_entry_row_add_suffix'
/usr/bin/ld: /home/runner/.cache/nim/adw_d/@madw.nim.c.o: in function `build__adw_1073':
@madw.nim.c:(.text+0x69ff): undefined reference to `adw_entry_row_new'
/usr/bin/ld: /home/runner/.cache/nim/adw_d/@madw.nim.c.o: in function `updateState__adw_1086':
@madw.nim.c:(.text+0x6d93): undefined reference to `adw_entry_row_remove'
/usr/bin/ld: @madw.nim.c:(.text+0x6d9d): undefined reference to `adw_entry_row_add_suffix'
collect2: error: ld returned 1 exit status
Error: execution of an external program failed: <Long Ass compiler command>
make: *** [Makefile:8: widgets_adwaita.md] Error 1
make: Leaving directory '/home/runner/work/owlkettle/owlkettle/docs'
stack trace: (most recent call last)
/tmp/nimblecache-946033505/nimscriptapi_1638491363.nim(187, 16)
     Error: Exception raised during nimble script execution
/home/runner/work/owlkettle/owlkettle/owlkettle.nimble(26, 8) genDocsTask
/home/runner/.choosenim/toolchains/nim-1.6.10/lib/system/nimscript.nim(273, 7) exec
/home/runner/.choosenim/toolchains/nim-1.6.10/lib/system/nimscript.nim(273, 7) Error: unhandled exception: FAILED: make -C docs [OSError]

For reference the compilation command, I removed it from the upper text-output so that it can more easily be scanned with eyes:

'gcc   -o /home/runner/work/owlkettle/owlkettle/docs/build_docs  /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@sstd@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@mgtk.nim.c.o /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@spure@[email protected] /home/runner/.cache/nim/adw_d/@mwidgetdef.nim.c.o /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@spure@[email protected] /home/runner/.cache/nim/adw_d/@m..@s..@s..@[email protected]@[email protected]@slib@[email protected] /home/runner/.cache/nim/adw_d/@mwidgetutils.nim.c.o /home/runner/.cache/nim/adw_d/@mwidgets.nim.c.o /home/runner/.cache/nim/adw_d/@madw.nim.c.o  -lm -lm -lrt -lgtk-4 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -lgdk_pixbuf-2.0 -lcairo-gobject -lcairo -lgraphene-1.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lcairo -ladwaita-1   -ldl'

I am currently guessing this is a cache issue with github actions. Based on a suggestion from demotomohiro (discord) I'm having the hope that maybe some caches are produced somewhere as part of this action and removing those caches before running the command will fix things?

[FR] Docs for components/modular organization of code.

It would be nice if it were documented how to organize a more complex/real world project. For instance, i want my "pages" code to be in their own Views directory, code for data access with something like litestor in another directory, etc. I like my main.nim file to be as sparse and clean as possible, with everything linked from directories that help "explain" how things work. Especially GUI-related code, which, even with something as clean as owlkettle, can still get kind of "hairy". It looks like the app_launcher example used to have components (i saw it referenced IRT components), but not anymore.

thanks

Memory leak using ORC.

in this nim code

import owlkettle

viewable App:
  counter: int

method view(app: AppState): Widget =
  result = gui:
    Window:
      title = "Counter"
      defaultSize = (200, 60)

      Box(orient = OrientX, margin = 12, spacing = 20):
        Button {.expand: false.}:
          text = "+"
          style = [ButtonSuggested]
          proc clicked() =
            app.counter += 1
        Label(text = $app.counter)
        Button {.expand: false.}:
          text = "-"
          style = [ButtonSuggested]
          proc clicked()=
              app.counter -= 1

brew(gui(App()))

when compiling with:

nim c -d:release -d:lto -d:useMalloc main.nim

valgrind reports leaks

==49509== Memcheck, a memory error detector
==49509== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==49509== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==49509== Command: ./main
==49509== 
==49509== Warning: noted but unhandled ioctl 0x644f with no size/direction hints.
==49509==    This could cause spurious value errors to appear.
==49509==    See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==49509== Warning: noted but unhandled ioctl 0x6444 with no size/direction hints.
==49509==    This could cause spurious value errors to appear.
==49509==    See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==49509== Invalid read of size 1
==49509==    at 0x4CF106C: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x4CF820B: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x4CF824C: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x4CE6E74: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x4CCD799: gsk_renderer_render (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x4B714C1: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x4B71E28: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x4C4BB77: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x52716FF: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.7200.4)
==49509==    by 0x5271862: g_signal_emit (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.7200.4)
==49509==    by 0x4C77202: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-4.so.1.600.9)
==49509==    by 0x52716FF: g_signal_emit_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.7200.4)
==49509==  Address 0x6596690 is 32 bytes before a block of size 4,096 in arena "client"
==49509== 
==49509== 
==49509== HEAP SUMMARY:
==49509==     in use at exit: 4,703,508 bytes in 20,876 blocks
==49509==   total heap usage: 296,643 allocs, 275,767 frees, 69,116,495 bytes allocated
==49509== 
==49509== LEAK SUMMARY:
==49509==    definitely lost: 3,240 bytes in 33 blocks
==49509==    indirectly lost: 19,232 bytes in 405 blocks
==49509==      possibly lost: 12,644 bytes in 85 blocks
==49509==    still reachable: 4,589,016 bytes in 19,650 blocks
==49509==         suppressed: 0 bytes in 0 blocks
==49509== Rerun with --leak-check=full to see details of leaked memory
==49509== 
==49509== For lists of detected and suppressed errors, rerun with: -s
==49509== ERROR SUMMARY: 16 errors from 1 contexts (suppressed: 0 from 0)

Document how to cross compile

Probably not a major concern presently but it'd be nice to easily cross compile. Debian derived distros do not have an easy process as they do not have a mingw64-gtk-3.0 package. So perhaps this bundle can help streamline the process.

I did use it with the following flags to generate a statically linked binary, but fairly certain that I just abused the C compiler as I could not launch the binary in Wine.

when defined mingw:
  --passL:"-static -lnetapi32 -lmoldname -lmqlogmgr -llinkinfo -lwebclnt -lrastls -lwebpdecoder -lcryptdlg -ld3dcompiler_38 -lksuser -lopengl32 -ldbghelp -lidq -lmingw32 -ldmconfig -lisign32 -lumpnpmgr -lusbcamd2 -linseng -lwiaservc -lcrypt32 -ld3dx10 -lrasppp -lmsrle32 -lmlang -lpolicman -lpng -ldsound -lmiglibnt -lwinsta -lfxsroute -lperfdisk -lsetupqry -luserenv -lperfnet -luniplat -lsyssetup -lwscsvc -lhttpapi -lpdh -lxapofx -limjputyc -losuninst -lmsisip -lsoftpub -latkmm-1.6 -lvssapi -ltraffic -lmmfutil -lxapofx1_1 -lpsapi -leappgnui -lmsdrm -lx3daudio1_6 -luuid -lcnetcfg -lperfos -lsysinv -lfxsdrv -lfreetype -lharfbuzz-gobject -lpixman-1 -lcryptsvc -lcmutil -lcatsrvut -lavifil32 -lurl -ldmvdsitf -lksecdd -lwinfax -licmui -lgdkmm-3.0 -lmf3216 -lmll_qic -lrtutils -lwofutil -ldpnet -lmodemui -lwow64cpu -lrdpcfgex -limskdic -lmf -lhmmapi -lmsasn1 -ltxfw32 -liashlpr -lntshrui -lmdminst -ld3d10 -lkeymgr -lharfbuzz_too -lmsdmo -lmsvcr120_app -ld3dcompiler_36 -ltiffxx -latrace -lwecapi -lbrowser -lmsoledbsql -lloghours -ld3dx9_40 -lshscrap -ld3dx9_30 -lphotowiz -lsynceng -lmtxdm -lmsvcr90 -lclfsw32 -lmobsync -lxinput9_1_0 -ld3dx10_33 -lmsadcs -ld3dx9_26 -lmsgrocm -lbootvid -ltiff -licwdl -lmsftedit -lappmgmts -lodbccp32 -ldwmapi -ld3dxof -lrasmontr -lmcastmib -lmsvidc32 -lsfcfiles -lwdigest -lperfproc -lpangomm-1.4 -lfastprox -lwshbth -lfontconfig -lmtxoci -lCINTIME -lwab32 -lcrtdll -lpangoft2-1.0 -lrstrtmgr -lupnp -lfxsperf -lsqlsrv32 -ld3dcompiler_33 -lwlanapi -ldhcpcsvc6 -lnshipsec -lnetman -lssinc -lopends60 -ld3dx11_42 -lpcre -lxapofx1_0 -lsetupapi -lmciqtz32 -ltsd32 -lmag_hook -lmslbui -lavrt -ld3dx9_24 -lsnprfdll -lrasmans -lntprint -lmigism -liissuba -lsamlib -ld3dx9_43 -liisui -ldbnmpntw -liprop -lncxpnt -llsasrv -lrpcss -ld3dx10_41 -lmll_mtf -lncobjapi -lwinmm -lntdllcrt -lwamreg -lcryptdll -leapphost -lrpcns4 -lktmw32 -lcredui -lmsgsvc -lwiarpc -linfocomm -loakley -lmmdevapi -lodbccu32 -ld2d1 -lsrrstr -lfcachdll -lacledit -ld3dx10_34 -luxtheme -lglu32 -ld3dcompiler_46 -lsensapi -lcmcfg32 -lmssign32 -ld3dx10_40 -lprintui -lmstlsapi -limeshare -ld3dx10_43 -lmsgr3en -lwdsupgcompl -lcairo-script-interpreter -ld3dx10_35 -lcorpol -lwldap32 -lwinhttp -lclasspnp -ld3dx9_42 -lsapi -lmsvcirt -lmsdadiag -lmsimtf -lpstorec -lscrobj -lftpmib -ld3dx10_36 -lglmf32 -lvmx_mode -lwsdapi -lwlanui -lfmifs -lx3daudio -laclui -llzo2 -lgdiplus -lwslapi -lbluetoothapis -lloadperf -lwdsimage -lhypertrm -lgiomm-2.4 -lmgmtapi -ldmivcitf -lappmgr -ladmparse -lntmarta -lcdfview -lserwvdrv -luntfs -ld3dx9 -locgen -lfreetype_too -lpathcch -ltapiperf -lntvdm64 -lwebsocket -lwpd_ci -lnetui0 -lwdsclient -lmapistub -ldbnetlib -lmsoeacct -ldhcpsapi -lmfc42 -lmll_hp -lsspicli -lmsvcr100 -lgmodule-2.0 -lquartz -ltsoc -levntagnt -lwtsapi32 -lsclgntfy -lwdscore -lhbaapi -lrpcdiag -luser32 -lusbport -liiscfg -lwevtapi -lefsadu -ld3dx11 -lnetio -lapphelp -lrasctrs -lodbccr32 -lgcrypt -ljpeg -liassvcs -lwlnotify -lsynchronization -liernonce -lasycfilt -locmanage -locmsn -lccfgnt -lmswsock -lpowrprof -lfxstiff -lshsvcs -lriched20 -lwinusb -liassam -lodbctrac -lsccbase -lcabinet -lw32time -lucrtbase -lcoadmin -lusp10 -lfldrclnr -ltdh -lexpat -lsqlxmlx -lumdmxfrm -linput -linetcomm -lwebcheck -ld3dcompiler_42 -lscesrv -lwlstore -lwebpmux -ladmwprox -lftpctrs2 -liedkcs32 -limm32 -lgmon -ld3dx9_29 -lscecli -lieencode -lactiveds -lmpr -ldpnaddr -lgpg-error -lxapofx1_5 -lstaxmem -lmsado15 -loleacc -lmsctfmonitor -ldrprov -lrasman -lrasadhlp -lcomuid -lpcrecpp -lp2pgraph -lwinspool -lUNIDRVUI -ldavclnt -lmtxex -lvfw32 -lhotplug -lsecur32 -limsinsnt -lpcreposix -ldciman32 -lgtkmm-3.0 -lodbc32gt -latl -lwebhits -liscomlog -ldimsroam -lmqcertui -lgptext -lcfgbkend -lmsoe -latmlib -lcscapi -lfxscfgwz -lmciole32 -lportabledeviceguids -lhttpodbc -lcomsetup -ld3dx10_37 -lmprmsg -lconnect -liaspolcy -lfxsocm -lslcext -lnetoc -ld3dx10_38 -llonsint -lperfts -lfribidi -lwintrust -ladvapi32 -lmsvcrt-os -lfeclient -lcomsvcs -ld3dx9_27 -lazroles -lodbcbcp -lcnvfat -lwsock32 -lwininet -ld3d8thk -lhgfs -ld3dx9_38 -ldsauth -lakscoinst -ldnsapi -lmciwave -lcdm -lrpcref -lmofd -lsmtpapi -linetmib1 -ld3dcsxd -lrasmxs -lwebp -lunistring -ldmutil -lseclogon -lglibmm-2.4 -lesent -lt2embed -liprtprio -lrasrad -lolecnv32 -ld3dx9_37 -ldsquery -licaapi -liisrtl -ldbus-1 -lmqperf -lspoolss -lw3ctrs -lirclass -liyuv_32 -lwdstptc -lcliconfg -lufat -lsfc -lmsvcr120 -lmsw3prt -lntdsbcli -lhnetcfg -lxapofx1_3 -lwevtfwd -lx3daudio1_7 -lwinipsec -lmsafd -lmfsensorgroup -lhnetwiz -lcomres -lguitrn -lclb -lwow64 -lexstrace -lmsir3jp -lmciseq -lfxsapi -lntoc -lwinsrv -ldwrite -loccache -lodbc32 -loledb32 -lresutils -lcabview -lmsvcr120d -lwmilib -lusbd -liis -lmprddm -lrassapi -lsrchctls -lodbcconf -linfoadmn -lapcups -lmspatcha -lruntimeobject -lcomsnap -lsrclient -lmfcore -liprtrmgr -liisutil -lmscat32 -lasp -lks -limjpcus -lmsutb -lw3core -lxinput1_3 -licwphbk -linfosoft -lversion -lipmontr -laudiosrv -lbasesrv -lcsrsrv -lcolbact -lndisnpp -lpintlcsd -ld3dcompiler_41 -ld3dx9_33 -lpautoenr -ld3d9 -lsfmapi -lws2_32 -lmsvcp60 -lhidparse -lmingwex -lp2pcollab -ldinput8 -lalrsvc -lmsmqocm -lsfc_os -lpangowin32-1.0 -lmydocs -llog -ldpapi -lsti -lnwprovau -lw3isapi -lrasauto -lmciavi32 -lmsobdl -lumandlg -lhlink -lschannel -ldskquota -lsxs -lx3daudio1_4 -liesetup -lhal -lnetshell -lw32topl -lregapi -lmprapi -lz -lcmpbk32 -ld3dx9_31 -lmsoert2 -ltaskschd -lmfuuid -ltapi32 -lnddenb32 -lprntvpt -ldbgeng -lwbemcore -ligmpagnt -ldsprop -lnetcfgx -lslbcsp -lx3daudio1_3 -lmsacm32 -ldismapi -lhttpmib -lrpchttp -lpcre16 -lcomctl32 -lqwave -lbatmeter -lgetuname -lcairomm-1.0 -linitpki -lwbemuuid -lxinput -lmmutilse -lmsdtcprx -lssdpapi -lfdeploy -lmsimg32 -lwindowscodecs -latkctrs -liiswmi -lfaultrep -licwdial -lvirtdisk -lntoskrnl -lmqsec -lschedsvc -ladvpack -lrpcrt4 -loeimport -lscarddlg -ldinput -lwbemupgd -lvdsutil -les -lshimeng -lregsvc -lmfc42u -lscrnsave -lstorprop -lsigc-2.0 -linfoctrs -lnormaliz -lmcdsrv32 -lntlsapi -lcimwin32 -lucrt -ld3dcompiler_37 -lwow64win -ldnsrslvr -ldiskcopy -lws2help -lbthci -ldigest -lrtm -lrsaenh -lisatq -lxapofxd1_5 -lPS5UI -linetcfg -llz32 -ladsldpc -lxaudio2_8 -lmshtml -lserialui -lnetid -llmmib2 -lwdscsl -lntdll -ld3dcsx_46 -lqutil -ldxerr8 -leventlog -licfgnt5 -lglibmm_generate_extra_defs-2.4 -lmsdtclog -lupnpui -laqueue -licm32 -lmprui -lnetui2 -lfxsui -lucrtapp -lmsls31 -ldpnhupnp -lhid -lautodisc -lmapi32 -lwdsutil -lrnr20 -lm -lcompstui -lsysmod -lpcwum -lwmiprop -lntlanui -lgpedit -lwebpdemux -limgutil -lmfplat -loledlg -lclusapi -ld3dcompiler_40 -llocationapi -lw3ssl -ldelayimp -lmsdtctm -leappprxy -lstrmfilt -lmqdscli -lxinput1_4 -ldxerr9 -llprhelp -ltcpmib -loleaut32 -laspperf -lstrmiids -lzoneoc -lfwpuclnt -lwdmaud -lcards -lssh2 -ld3dx9_25 -lmssip32 -lwer -ldmoguids -lds32gt -ladsiisex -lurlauth -lnetlogon -lmqutil -lepoxy -lsecurity -lauthz -lmqrtdep -ld3d12 -liphlpapi -ladptif -lxinput1_1 -limjp81k -lbthprops -lseo -lole32 -lsens -ldsuiext -lmincore -lesentprf -lhtrn_jis -llocalspl -lpschdprf -ldevobj -lwiadss -lnddeapi -lmsvcr110 -ld3dx9_28 -lnntpapi -ladsiid -lPSCRIPT5 -ldssec -lvgx -lfxsst -lsyncui -lsdhcinst -lkerberos -ld3dcompiler -ld3dx11_43 -lscredir -lmstask -lcurl -ld3dx9_39 -ld3dcompiler_43 -lqmgr -lpng16 -lhidclass -lrastapi -lavicap32 -lwimgapi -lcryptxml -lmchgrcoi -lxinput1_2 -lmingwthrd -lmtxclu -lsmtpctrs -lhttpext -ld3dcompiler_39 -lduser -lmqise -limjpdct -lwmcodecdspuuid -lchtskdic -lfilemgmt -lUNIDRV -lperfctrs -lkd1394 -lwmi2xml -ldpvoice -lidn2 -lscrrun -lshlwapi -lmsyuv -lpsbase -lipnathlp -lcryptsp -lmcicda -lshcore -ld3dx9_41 -liscsidsc -ld3dx9_32 -lmqrt -lnetui1 -ld3dcompiler_35 -lwdsclientapi -lpolstore -lpe-parse -leappcfg -lw3dt -lrasser -ltbs -lx3daudio1_2 -lfltlib -lsisbkup -lstreamci -lmsvcr90d -llpk -ldcomp -lagentanm -lcfgmgr32 -lshdocvw -lwmi -lmqupgrd -lnetplwiz -lwow64mib -luniime -ldxguid -loemiglib -lwkssvc -lmsports -lverifier -lskdll -licmp -lquery -ld3dcompiler_47 -ldssenh -lintl -lsigtab -licwutil -lmsvcp120_app -lpidgen -lieakeng -lw3tp -lwinhvemulation -lmsrating -lutildll -lqosname -lslc -lframedyn -ldxgi -lwshatm -lroutetab -lolecli32 -lraschap -lkdcom -lcryptext -lnetrap -lcharset -lhostmib -lpropsys -lntdsapi -ld3dx9_36 -lcscui -lmsi -lx3daudiod1_7 -lresutil -lpthread -lamstrmid -llzma -lwinhvplatform -lmsdtcstp -lcertcli -lshell32 -ld3dcsxd_43 -lrdpwsx -lsensorsapi -lmqad -lipxsap -lmsdart -lhtui -lsvcpack -lwinrnr -lgthread-2.0 -lgdi32 -lcscdll -ldpnlobby -llargeint -ldsound3d -lshfolder -lmfreadwrite -lwinscard -ltsbyuv -lrasdlg -lsenscfg -lcatsrv -liconv -lmsv1_0 -lmsvcr80 -lksguid -lprofmap -lharfbuzz-subset -lwiashext -lxapofx1_2 -lsnmpmib -lwmiaprpl -lscript -lsrvsvc -lwinpthread -lp2p -lddraw -lmfplay -lcryptnet -lcomdlg32 -lmsgina -lncrypt -lipsecsvc -lrdpsnd -lurlmon -lndis -ljsproxy -lwabimp -levr -lffi -lsnmpapi -ld3dx10_39 -lconsole -lbatt -lwscapi -lpstorsvc -lfxswzrd -lgailutil-3 -ldmdskmgr -ldevmgr -lkernel32 -ljet500 -ldimsntfy -lwmisvc -lrasapi32 -lvcruntime140_app -lscrnsavw -lmsdtcuiu -ludhisapi -lntmsapi -lmcd32 -lntlanman -ld3dx10_42 -lmsvfw32 -lsti_ci -lnpptools -ld3dx9_34 -lfontsub -lolesvr32 -lfxst30 -lmscms -limagehlp -licwconn -lcryptui -lxapofx1_4 -lx3daudio1_5 -lbcrypt -lwlanutil -lwindowsapp -lhtmlhelp -ld3dx9_35 -lnewdev -lmsobmain -lunimdmat -ljasper -lcmdial32 -lshimgvw -lsamsrv -ld3dcompiler_34 -lndfapi -liisadmin -ltsappcmp -lmidimap -ldevrtl -lclbcatq -lslwga -lgpkcsp -ldxva2 -ld3d11 -ldhcpcsvc -lbz2 "
  --passL:"-L /home/jason/Downloads/gtk3.0-mingw/x86_64-w64-mingw32.static/lib/"

App doesn't quit when closing window

When I close the window the app still stays running in the background, is there a way to run a callback when the window is closed so the app quits?

Counter example wasn't compile

When I try to run/compile the counter example on the start page with "nimble run", then comes the error "Error: type mismatch: got 'array[0..0, ButtonStyle]' for '[ButtonSuggested]' but expected 'set[ButtonStyle]' ".
The error relates to source line "style = [ButtonSuggested]", when I changed it to "style = {ButtonSuggested}" it compiled and run.

I used owl kettle on Apple M1 Ultra Ventura 13.3

[FR] enable github discussions feature

hi,
any chance you might enable github's Discussions feature for this repo, so people can ask questions for general support and/or to clarify things prior to creating an issue report? It would probably cut down on invalid bug reports, questions in the issue tracker, and help new users get started. Users could eventually help each other, and save owlkettle devs some time, etc.

I'm not in favor of projects using ephemeral chat for support because the same questions get asked and answered over and over again, and i don't like bothering people with something basic that has already been asked and could have been documented by forum software.

thanks

Error: undeclared identifier: 'DropDown'

I tried to run the drop down example in the widgets directory.

I got an undeclared identifier error.
/home/kolmogorov/Documents/dev/owlkettle/examples/widgets/drop_down.nim(49, 20) Error: undeclared identifier: 'DropDown'
candidates (edit distance, scope distance); see '--spellSuggest':
(1, 7): 'drop_down'

Has the widget been removed?
I have tried to rename the module to drop_down_example.nim to avoid any conflict and I got the same error!

error in Win 10

Good morning, I'm trying Owlkettle on Windows 10, but Nonn I can understand and above all to solve the following mistake. Maybe there is no qulacosa? I don't know! Thanks for your attention (on Linux it works very well).

C:\Users\Martin\Desktop>nim c test.nim
Hint: used config file 'C:\Users\Martin\scoop\apps\nim\2.0.0\config\nim.cfg' [Conf]
Hint: used config file 'C:\Users\Martin\scoop\apps\nim\2.0.0\config\config.nims' [Conf]
..............................................................................................................................................
CC: ../scoop/apps/nim/2.0.0/lib/system/exceptions.nim
CC: ../scoop/apps/nim/2.0.0/lib/std/private/digitsutils.nim
CC: ../scoop/apps/nim/2.0.0/lib/std/assertions.nim
CC: ../scoop/apps/nim/2.0.0/lib/std/formatfloat.nim
CC: ../scoop/apps/nim/2.0.0/lib/system/dollars.nim
CC: ../scoop/apps/nim/2.0.0/lib/std/exitprocs.nim
CC: ../scoop/apps/nim/2.0.0/lib/std/syncio.nim
CC: ../scoop/apps/nim/2.0.0/lib/system.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/parseutils.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/math.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/unicode.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/strutils.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/dynlib.nim
CC: ../scoop/apps/nim/2.0.0/lib/windows/winlean.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/times.nim
CC: ../scoop/apps/nim/2.0.0/lib/std/private/win_setenv.nim
CC: ../scoop/apps/nim/2.0.0/lib/std/cmdline.nim
CC: ../.nimble/pkgs2/owlkettle-2.2.0-1920752fd3efe5207267e351898fdcc1674d25d8/owlkettle/gtk.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/hashes.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/collections/sets.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/collections/tables.nim
CC: ../.nimble/pkgs2/owlkettle-2.2.0-1920752fd3efe5207267e351898fdcc1674d25d8/owlkettle/widgetdef.nim
CC: ../.nimble/pkgs2/owlkettle-2.2.0-1920752fd3efe5207267e351898fdcc1674d25d8/owlkettle/widgetutils.nim
CC: ../scoop/apps/nim/2.0.0/lib/pure/asyncfutures.nim
CC: ../.nimble/pkgs2/owlkettle-2.2.0-1920752fd3efe5207267e351898fdcc1674d25d8/owlkettle/widgets.nim
CC: ../.nimble/pkgs2/owlkettle-2.2.0-1920752fd3efe5207267e351898fdcc1674d25d8/owlkettle/mainloop.nim
CC: ../.nimble/pkgs2/owlkettle-2.2.0-1920752fd3efe5207267e351898fdcc1674d25d8/owlkettle.nim
CC: ../.nimble/pkgs2/owlkettle-2.2.0-1920752fd3efe5207267e351898fdcc1674d25d8/owlkettle/dataentries.nim
CC: test.nim
Hint:  [Link]
C:/Program Files/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find Files/msys64/mingw64/bin/../lib: No such file or directory
C:/Program Files/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find Files/msys64/mingw64/bin/../lib: No such file or directory
collect2.exe: error: ld returned 1 exit status
Error: execution of an external program failed: 'gcc.exe   -o C:\Users\Martin\Desktop\test.exe  C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@sstd@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@sstd@sprivate@swin_setenv.nim.c.o C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@[email protected]@[email protected]@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] 
C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@spure@[email protected] C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@spure@[email protected] 
C:\Users\Martin\nimcache\test_d\@[email protected]@[email protected]@[email protected] 
C:\Users\Martin\nimcache\test_d\@[email protected]@[email protected]@[email protected] 
C:\Users\Martin\nimcache\test_d\@m..@sscoop@sapps@[email protected]@slib@[email protected] C:\Users\Martin\nimcache\test_d\@[email protected]@[email protected]@[email protected] 
C:\Users\Martin\nimcache\test_d\@[email protected]@[email protected]@[email protected] 
C:\Users\Martin\nimcache\test_d\@[email protected]@[email protected]@sowlkettle.nim.c.o 
C:\Users\Martin\nimcache\test_d\@[email protected]@[email protected]@[email protected] C:\Users\Martin\nimcache\test_d\@mtest.nim.c.o  -L
C:/Program\ Files/msys64/mingw64/bin/../lib -lgtk-4 -lpangowin32-1.0 -lharfbuzz -lpangocairo-1.0 -lpango-1.0 -lgdk_pixbuf-2.0 -lcairo-gobject -lcairo -lgraphene-1.0 -lgio-2.0 -lglib-2.0 -lintl -lgobject-2.0 -LC:/Program\ Files/msys64/mingw64/bin/../lib -lcairo   -Wl,-Bstatic -lpthread'

I'm not a Windows fan and therefore I don't know how to use it very well, but I may need to do interfaces for that system.
Thanks for any help you can give me!
Bye by Martin A.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.