Puny GUI – A tiny cross platform GUI Kit in Janet
ahungry.com
ahungry.com
I wouldn't say never use an minimalist framework. It can be handy for embedded debugging tools or for toy projects. But I wouldn't use one of these things for an application that I thought might have a few thousand users and some sort of life span.
I've found nativefiledialog to be quite good for that use case
Let's not forget just how low the bar has been set by Electron. Microsoft Teams manages to use 600MB of RAM.
Some reported that moving from Qt to Dear Imgui resulted in a codebase three-time smaller.
I made applications with Nuklear that runs on Android, iOS, macOS, Windows and share the same main C code. For me, it's a dream come true if you create a cross-platform application that needs a simple GUI.
Dear ImGui is also fantastic and more complete than Nuklear.
What I like a lot with Nukear and Dear Imgui is that you have a GUI that is GPU accelerated and so can be updated at 60 FPS without burning resources.
These are meant for use in games that already do this. They are not suitable for building regular apps.
How do you even compile C code for Android / PlayStore?
Android NDK
The Android NDK is a toolset that lets you implement parts of your app in native code, using languages such as C and C++. For certain types of apps, this can help you reuse code libraries written in those languages.
Debugging is working smoothly, I was surprised how good the experience was.
My setup is that Window run in a VM (Parallels) from macOS.
I can then open the iOS code from XCode and the Android from Visual studio and switch very quickly between the targets.
In that way, I always commit versions that I already tested and debugged on all the targets I need to support.
You are right accessibility is not supported by those 2 frameworks and that's an issue.
One of the applications I wrote simulate a LED protocol and so you just need to launch it and then use it over the network from a server.
Using something like luastatic[1], with whatever Lua libraries you want (including IUP), you can get something pretty similar to this system, except of course you'd be using Lua instead of Janet. Janet is really interesting and that alone justifies this framework very well.
However, even in the python sample, I couldn't find anything that was just "Download, Unzip, Modify" to start creating (all seem to have cumbersome install steps or hoops to jump through - I basically wanted something that was 0 configuration/installation, for fast iteration and development).
The new crop of immediate mode cross platform GUI libraries are more interesting (such as nuklear and Dear Imgui). I also did some experimentation with these libs a few days ago: https://liuliu.me/eyes/write-cross-platform-gui-in-swift-lik...
They're also completely inaccessible to blind people (using screen readers) and probably some people with other disabilities as well. IUP is at least partially based on platform controls. I'll take usable over interesting.
There should/could be open accessibility APIs in each OS which sit between (e.g.) screenreader software and custom UI frameworks.
It's not so active these days, admittedly.
Applications AOT compiled with the Flutter SKD are surprisingly lean (i.e. compared to Node/Electron) and not much larger than Qt applications.
I think "cross-platform" should include mobile.
In the end, this feels like a an appraisal of IUP and Janet more than a demo of anything new. If that's the case, then familiarity with your stack is more important for this kind of productivity than anything else, so trying something new is less appealing to me.
But I was curious about Janet, so seeing some examples was nice.
But you are spot-on that this is more showcasing the joining of various other things out there, rather than anything innovative (although I do plan to add more and extend the existing convenience wrappers, such as wrapping the IUP calls in a hiccup-like DSL using Janet macros).
To simplify a little, you pass these libraries the events from the windowing system and it gives you a list of triangles back. Then you feed the triangles to the GPU and you're done. All the logic (and nothing but the logic) is done by the GUI library.
This is why dear imgui is perhaps the most popular GUI library in the world. It's used in a lot of game development tools, etc.
If anyone is interested in the topic, I am writing a lightweight flexbox-based retained mode GUI layout rendering library that integrates like imgui/nuklear. Give me a shout if you want to know more.
I got inspired by Raph Levien's talk on Rust and GUI layout [0] and realized that a simple flexbox layout algorithm can be implemented really efficiently.
So I started making a prototype in C (also a small proto in Rust), using a densely packed array to implement a DOM-like tree. The tree nodes have short strings, boxes (with border, padding, etc), images (texture coordinates in an atlas), layout constraints, containers, etc. Flexbox layout is applied to the tree in linear time (and constant memory!) and then the tree is traversed to output an ordered list of axis aligned rectangles.
The output list can be fed to the GPU, where a special (but simple) shader draws clipped triangles that get applied with textures, msdf font, etc. The whole GUI gets rendered with a single draw call.
This all can be done with very fast performance (sub-millisecond for layout and rendering, excluding GPU latency). There are other implementation details that make it efficient for cache (sizeof(node) == cache line), no recursion, no memory allocation, no unbounded loops, no system calls, etc.
I'm fairly convinced that this approach should be enough to cover 80% of modern GUI paradigms. However I don't have the time or the interest to build a complete widget set GUI library.
Right now I'm sporadically working on the project with a goal to make a game UI with clickable, scrollable and scalable text and images with a modern layout. Right now all I have to show is some ugly text and rectangles (but with a very nice layout), but it's a start for a project with potential.
[1] https://gist.github.com/9214/dfa15d37342065dbf368eae35abcdc3...
I'm expecting a GraalVM rejoinder from someone. For anyone who's used GraalVM (particularly with Clojure) - what are the downsides and limitations?
Must look into GraalVM at some point, but, as someone new to Clojure, I'm wary of spending too much time on tooling yet. I've found in the past I can tinker so much with such things that it interferes with getting fluent with more fundamental stuff.
I'd be interested to see if either now or in the future Clojure + JavaFX in GraalVM would be feasible.
Edit: I don't quite get the install size issue - I thought native image was an entirely standalone executable?
Ironically they have to thank Oracle for doing something that Sun was religiously against, having an AOT compiler as part of the free beer Java layer.
If the author's app takes 10 seconds to boot, I am afraid they need to blame either Clojure or their own code for that.
Granted, this usually only comes from those that don't bother much to learn about the underlying platform and are sometimes even agressive against what actually made their favourite guest language possible to exist.
maybe i'm arguing semantics, but i don't think it's fair to say that the JVM "made Clojure possible" -- that's like saying "C made Python possible because CPython is written in C".
iirc the JVM was chosen as a backend because that's what Clojure's creator had to work/interop with. and i think that's generally the case with "guest" languages -- there's an environment you want to write code for (JVM/ browser), but you don't want to use its "official" language (Java/JS), so you create a new language and adapt it to run there.
and sure, reusing the Java stdlib and other existing code can help bootstrap a language, no doubt about that, but it's a stretch to say it makes it "possible"
If you are making something serious, you will have to implement at least the GUI layer separately for all platforms.
Qt? Tk? I've used both cross-platform and both work great for desktop operating systems (and unlike in the olden days, Tk's themed widgets actually look reasonably native now). Qt's only downside is the licensing and the sheer size of it, and Tk's only downside (for my use cases) is the lack of an embeddable browser widget; in both cases these are issues regardless of platform.
The actual cross-platform issues, from what I've seen, are more to do with the non-GUI pieces. For example, Windows and macOS/Linux printing are wildly different from one another, and all three operating systems have wildly different strategies for packaging and distributing applications (especially when writing the program in a scripting language like Python or Ruby or what have you instead of something precompiled like C++ or Rust; with Linux this is trivial, and with macOS this is less trivial but manageable, but with Windows this is a royal pain in the ass).
On another note, I'm currently looking into Avalonia and .NET Core as another potential option in this space; from preliminary testing, .NET Core looks like it mostly addresses the issues I've encountered (it certainly makes it easy to cross-compile for Windows/Mac/Linux, and I'm hoping it'll eventually subsume Xamarin or portions thereof to enable easy Android and iOS builds, too), so whether or not this becomes my go-to hinges on whether or not Avalonia itself is ready for primetime (and while simple examples seem to be promising, as are more complex examples like the Avalonia version of ILSpy, I'm still actively investigating).
Comparing Qt v. Tk v. native on Windows and macOS (and Linux, but there is no "native" toolkit so there wasn't anything to compare), not once did I notice any actual significant difference. macOS is the only one that required the slightest bit of adjustment (for the stuff I wrote; no idea about the Qt or Tk programs others wrote), and that's only to make sure it uses the system menu bar instead of shoving one into the top of the window as is normal for Windows and (usually) Linux.
I have not seen a Qt app on macOS that did not stand out like a sore thumb on the very first glance.
Divergence in "behaviours" and "generally agreed-upon layouts" is possible even with native toolkits, so I fail to see how Qt or Tk are a relevant factor here (both of them give the programmer the necessary tools to match the native behavioral and layout conventions, just like the native toolkits do).
Tk definitely has a disadvantage in the "accessibility" category, but Qt literally uses and abstracts the native accessibility interfaces¹, so in Qt's case this should be a non-issue (beyond the typical considerations for software accessibility that apply even for native toolkits, like, you know, actually leveraging and testing those features).
> I have not seen a Qt app on macOS that did not stand out like a sore thumb on the very first glance.
Okay, but by virtue of knowing what Qt even is, I'd wager that you ain't an ordinary user. The vast majority of end users will neither notice nor care (especially given that there's an abundance of commonly-used software that deviates from the typical macOS UX even without Qt, e.g. Office and Chrome, or pretty much every single app using Electron or CEF or some other browser-as-UI approach). The only thing that truly matters is whether or not the software works and is usable, and Qt doesn't really pose any obstacle there (and Tk only does if accessibility is a concern - which I'd argue it should be, but it's at least no worse than the status quo).
----
Fltk will let you do it in 700KB with no dependencies. (100KB if you're crafty). Juce, Qt, pyQt, opengl+imgui, opengl+nanogui all work well. There is also gtk, Tk, wxWindows ...
Where are you getting this idea from?
Now, outside of macOS this might not be much of a problem since Windows users were beaten into submission to accept any arbitrary look and behavior and Linux users never had a choice anyway.
If you are worried about the shading on your buttons then you must have had all your problems solved already.
But it isn't just "buttons looking different", it is also "buttons behaving different". As an example (that i often find annoying in programs with long lists), under Windows Qt scrollbars do not behave like native Windows scrollbars: shift click in Windows should cause the scrollbar to scroll at the point you clicked (like middle click on most X toolkits) but Qt ignores that.
Also it is "buttons not integrating properly". On macOS it is very common for example to have system-wide addons (services i think they are called) that add additional functionality to text fields, like "search with google", "text to speech", "show definition", etc. This doesn't work when a toolkit does its own text field controls. You can also see a similar thing on Windows: GTK+ applications (e.g. GIMP) ignore the emoji panel in their text fields that appear with Windows+; but native text fields work fine with it.
Now note that i'm not saying this is something that matters for all sorts of applications or is always a deal breaker (especially nowadays that, as i wrote above, most users outside of macOS have been conditioned to accept these), but it isn't something that you can handwave away as "having a different shade" either.
The more serious issue that nobody here has yet mentioned is lack of accessibility, e.g. for blind users with screen readers, in many toolkits. I say that is a deal-breaker if you're developing any kind of application that someone is going to use in their job, education, or other important tasks, unless the task is already inherently visual in nature. Qt has passable accessibility on Windows, Mac,and desktop Linux. GTK is accessible as part of GNOME. Electron, for all its faults, is as accessible as Chrome (pretty good these days). FLTK, FOX, Nuklear, TK, and a thousand other toolkits have zero accessibility. I've grown weary of bringing this up, and some of you may be tired of seeing it, but I feel compelled to do everything I can to make sure nobody overlooks this point, lest someone develops an inaccessible application that prevents someone else from doing a job, taking a course, etc.
Edit: I realize that was a rant. What rubbed me the wrong way about your comment was the suggestion that the problems with cross-platform toolkits are mainly cosmetic things or extra functionality that only spoiled Mac users care about.
But also yes, not every program has to care about these, including accessibility. An image editor or a level editor for some game or some internal and/or throwaway tool that has a very explicit "audience" has no reason to bother about these.
ldd app.bin|rg -o '/usr/lib[^ ]+'|xargs stat -L -c %s|perl -lne'$s += $_; END {print $s}'
38120904
I'm digging in to Chaos and then Janet after that.
> Puppy is an app
OK, you run 'Puppy'. It doesn't do anything.
> RandomHost is 'https://dog.ceo/api/breeds/image/random'
OK, 'RandomHost' is a constant, looks like a URL
> Get an image from RandomHost
OK, I think you meant Set Message to Read RandomHost retreiving UUENCODE.
> No. Get an image using json
Not the previous thing. I think you meant Set Message to Read RandomHost retrieving JSON, field Message.
> Get Image at Message
OK. I think you meant Read the URL Message and retrieve an image file
> Show the Image
OK. Displaying the Image on the screen
> Add Repeat Button
OK. Displaying a button named 'Repeat'
> App is While on Repeat, do the Display.
OK. App is set. Do display, Wait for Repeat button, Loop
> Puppy?
Puppy is an application:
Repeat
RandomHost = 'https://dog.ceo/api/breeds/image/random'
Message = fetch(RandomHost, JSON)."message"
anImage = fetch(Message, DATA).ensure(IMAGE_TYPE)
Display.reset(Items [
Image: An Image,
Button: Repeat text "Repeat"
])
ClientSideWait Repeat.onPress
Forever
> Problems?Your app can run.
You have eight error conditions to discuss. Use 'Talk about errors' to decide how to handle them. Right now, the answer is 'ignore first, or just explode'.
>Push
Pushing transcript to GitLab.... Building App.... Pushing Build to GitLab.
> Move button above image.