Evolving THE GUI definition?
Please chim-in with views or ideas to sort things out, correct or add. Are we already further, or yet not here at all?:
What's needed?
With many platforms and gui toolkits around, it seems they all have their basic platform- and toolkit specific way, often the nitty-gritty way. These ways evolve from the constraints of the specific projects. Choosen paths and specific features.
Whereas, the constraints of application developers may many? times let them to wanting something different. A most simple yet powerful and elegant way to write logic and and easily getting, adjusting, or (re)definig their GUI.
What's the big (i)deal?
A straight-forward way to code, while getting good GUIs with a native interface on each platform (a basic GUI even automatically), without any external dependencies. Of course with the option to refine widgets, or mixing-in elements defined by an arbitrary selected other toolkit (or even mixing different toolkits)? Immediate mode? Canvas-in-canvas?
What I found for Nim:
What do do?
The challenge at hand seems to be, to unite things into a nim "specification" for default widgets, widget customizations, toolkit selection, and theming. Separating concerns with an eye on working with a shared nim interface.
How? Planning a joint effort? Allow application coders to select their default toolkit, and add their optional customizations, which can draw GUI elements as native-widget/some-toolkit-widget/custom-or-pure-figment-sprites??
Has Fidget already come reasonable close to finding some "common event system" logic that works for input/output of events from different toolkits (https://github.com/simonkrauter/NiGui/issues/11)? Is the only thing left for an integration, to add access to native interfaces (i.e. NiGui and webgui) to Fidget v1 or v2?
Or the other way around? A NiGui based (native interface) abstraction that can setup spaces to call other toolkits to draw their widgets within?
Other's Work? (at least some notable pointers)
Multi-backend, simple switch between Tk,Qt,HTML. (https://github.com/PySimpleGUI/PySimpleGUI)
"Markup"-like custom GUI code, that's already visually recognizable in the code (wysiwyg ;-). (https://github.com/alfiopuglisi/guietta/)
Default automatic (or "implicit") GUI, based on argparse interpretation and an optional annotation. (https://github.com/chriskiehl/Gooey)
Default automatic CLI, even without any argparse helper: Automatic argument parsing, and validation, CLI-option documentation, as well as function execution, simply by adding commented variable and function definitions. (https://github.com/TangoMan75/shoe)
I don't know about all your other ideas, but https://github.com/c-blake/cligen is pretty automatic as CLIs go. The shoe approach of just populating variables still leaves a need for users to specify activity. cligen just takes that one step further to have the user specify the proc instead - then the activity is whatever the proc does.
In taking that one step, it makes it easy for application logic to be agnostic with regard to if it is even inside a CLI at all (or if cligen is even installed at all!). Indeed, one could wrap the very same proc(s) in a CLI or a web form or GUI form (for simple procs) discussed briefly in one of many closed issues. This kind of design could blur the lines between "library", "cli", "web form", "GUI" which seems to be the kind of overall vibe I am getting from your post. Just one possible direction, of course.
Interesting ideas! I'm not sure it'd be possible or even desirable to directly share end user code / widgets between frameworks though.
However, there's lots of ideas and core libraries that can be shared. Things like Windy and nim-native-dialogs are fantastic core libraries!
Personally, I split out my CSSGrid library from Fidgetty for this sort of eco-system thinking. CSS-Grid is (in my humble opinion) an awesome tool for complex table-like layouts. In theory css-grid can be usable for lots of different GUI's / TUI's / etc.
The challenge at hand seems to be, to unite things into a nim "specification" for default widgets, widget customizations, toolkit selection, and theming. Separating concerns with an eye on working with a shared nim interface.
This would be challenging. Making re-usable widgets across toolkits requires deciding on various trade-off's and design patterns so it doesn't seem like it'd be a useful goal in itself.
However, sharing ideas and being able to "translate" widgets manually, or even using event handling procs could be super helpful.
Has Fidget already come reasonable close to finding some "common event system" logic that works for input/output of events from different toolkits (https://github.com/simonkrauter/NiGui/issues/11)? Is the only thing left for an integration, to add access to native interfaces (i.e. NiGui and webgui) to Fidget v1 or v2?
Fidget's event system model is pretty limited when you want to do more advanced things.. I ended up doing a partial re-write of events in Fidgetty. :) It's still simple, but captures mouse events to one node ahead before widgets / nodes are visited. This makes it easy to handle overlapping menu's, etc. It likely wouldn't be a good fit for most native ui-toolkits though.
Hmmm... and another thought:
One pattern I've ended up embracing in Fidgetty has been Nim's "enlightened procedural style". Essentially just using proc's that when called modify the current environment, whatever that is. With Nim's templates you can make this work with functional or object-oriented style backends. :)
This works very well for themes where it's literally just "set this color". It could be feasible to create a common theming library to be shared across multiple UI projects sort of like Julia's plots project. Though of course there's limits and you can only do the final 10% using UI specific details.
Unlike with events, there's usually a one-way mapping of "set widget color to blue" and "center button" to most any UI system. Providing custom user behaviour is harder to translate -- I think this sort of aligns with @cblake's mention of user proc's to define behaviours vs the data.
I suspect you are asking for some kind of great cross-platform GUI framework. Sadly, IMO, having a good universal cross-platform GUI is nearly impossible, for all language,s for multiple reasons.
One of the more basic reasons is handling the OS environment. Some environments, such as Windows or Linux are imperative in nature. Others, such as Android and HTML/JS are intrinsically reactive in nature. Converting from imperative to reactive is nearly impossible to do automatically. Converting reactive to imperative is...easier but makes for ugly unmatched code. Just in case someone does not believe me, try converting the following imperative script even by hand:
echo "welcome to the hello program"
echo "enter a name or the word 'exit':"
var name = readLine(stdin)
while (name != "exit"):
echo "Hello, " & name
echo "enter a name or the word 'exit':"
name = readLine(stdin)
echo "Thanks for playing"
into Javascript, where the input comes from an <input> and the output goes to a <div> or <pre>. The goal is not get the browser window to "freeze" forever.
Impossible? Not if you rethink it and write it differently. But you end up with a very different looking program that has to handle state. And converting "with a Macro" is a ... nightmarish task. (I sort of did it once, but it was filled with SO many restrictions.)
So, instead, I'd recommend stating your project's goal to get a better answer.
So, what is your goal? If writing a game, then there some cross-platform systems such as Godot which have limited Nim support. If writing a desktop app, are you wanting the "widgets" be truly universal or should they look native to each desktop environment? With more details, I'm happy to help out.
What if,
every widget is an executable, is written using what ever gui lib, tied together using a lightweight inter-process bus to present itself as a singe app
for inspiration, look at DAW's and their VST's, AU's etc.
then, forget about native look and feel. Applications should be written to the their use case and not to a marketeers ... dream. Again, look at VST's, bright and colour full and very fit for use.
why don't commandline tools have some "clever json" inside them so they can be used in a "clever" "node red" like tool... if you want gui?
try converting the following imperative script even by hand:
interesting challenge!
this is my solution using nimib's nbKaraxCode (karax without boilerplate):
nbKaraxCode:
const
helloId = "helloId"
inputId = "inputId"
var
hello = "welcome to the hello program"
name = ""
karaxHtml:
p(id=helloId):
text hello
label:
text "enter a name or the word 'exit':"
input(id = inputId, `type` = "text"):
text name
button:
text "Enter"
proc onClick() =
name = $getVNodeById(inputId).getInputText
hello = "Hello, " & name
you can see it in action here: https://pietroppeter.github.io/nblog/drafts/hello_name.html
it did not require any particular reasoning, it is a pretty straightforward translation. it could possibly benefit from some karax widgets to simplify even further. also I guess I could avoid the button, but I do not know how to do it.
it does not seem too different from the original but I guess state is indeed managed somewhere, would be interested in hearing your thoughts about it :)
You don't handle the exit word at all. In the input section, you will probably have to add an if case to output the "Thanks for playing" part.
I guess the problem in the conversion is the way you end the program. Do you hide the button, once exit has been given as input ? Do you leave the button, but make it not react anymore to any click event ? I guess that this is the kind of problems @JohnAD wanted to raise.
summary of Nim GUI's libraries.
Actually we have more than 20 currently. See list just above this heading: https://ssalewski.de/gtkprogramming.html#_introducing_gtk I have recently added the www links.
I only tried to make a picture, but you quoted the wrong parts of my picture. I will explain what is wrong today: Do you know prof Wirth? You probably know that he created Pascal. What not a lot of guys know is that after he created Pascal he continued with new languages, Modula and after that he created Oberon. Now Oberon https://en.wikipedia.org/wiki/Oberon_(programming_language) is a language that is different from the rest of most programming languages because of a couple of things: It compiled like a rocket, was type safe, completely garbage collected, it did have modules and objects, was safe and a lot more. It was designed in a reaction to Ada and C++. Most of all, it was simple.
The problem is that this language was designed in the 1980s and still today nobody knows it. Why? I don't know. Maybe it was because "the industry took off", but it was miles ahead of both Ada and C++. Oberon was a very well designed language.
If an operating system was designed in Oberon then you donĀ“t have to worry about a lot of things. Then you would be productive and you wouldn't need to wait for hours because it is compiling. And Oberon also only compiles the modules. There is no linker, so you end up with lots of tiny compiled modules.
I still don't believe you understand what I am trying to say. So I am going to repeat what I said before:
So, to answer your question, fixing something like this is probably impossible, because of all the hardware and software that is involved. You just can't push the picture of an elephant into a mice-like device and the other way around.
The only thing that does work is simplicity, but we are miles away from that.
I think Nim + some form of Web GUI is the best option for now. Not because it's better, but because you can re-use your web skills and new things you learn about web, you later will be able to re-use in other projects.
Other Nim GUI options require learning new API that will be dead knowledge as you probably not be using it for any other project. They are just not mature or good enough to justify paying such price.
The problem is that this language was designed in the 1980s and still today nobody knows it. Why? I don't know. Maybe it was because "the industry took off", but it was miles ahead of both Ada and C++. Oberon was a very well designed language.
Oberon is actually unusable by today's standards:
But even by yesterday's standards it really was worse than C++ and Ada.
That is Oberon the language. Oberon the OS was impressive but there is no reason to believe it would have kept its simplicity if enough users dragged it into the mainstream. I'm also not sure if it wins prizes when compared to a Lisp machine.
Again, look at VST's, bright and colour full and very fit for use.
I just want to add my take on the story of VST plugin GUIs. They:
Lately, there's been more and more plugins appearing with really advanced and comfortable UIs, but it's definitely not the norm yet and I wouldn't present the field as a whole as some beacon of brilliance in the matter. On the other hand, the most advanced and popular plugins are those taking the UX seriously: there's only so much filter basic filter variations you can make, but how you allow the user to operate them really separates the successful products from run-of-the-mill ones.
Oberon is actually unusable by today's standards:
That is obvious.
But even by yesterday's standards it really was worse than C++ and Ada.
Do you think so? You need to keep in mind the hardware that Wirth did have and the goals that he wanted to achieve.
The language was simple, but we all know what the problem with a simple language is: People always want new features. I still believe that it was better than C++ and that is because C++ has so many features and the compile time is abysmal.
About Ada, I don't think that at that time they even did have a working compiler for the language, and if they did then it would have cost a fortune.
That is Oberon the language. Oberon the OS was impressive but there is no reason to believe it would have kept its simplicity if enough users dragged it into the mainstream. I'm also not sure if it wins prizes when compared to a Lisp machine.
But the OS wasn't designed to win prices. Wirth wanted a simple and usable OS and with that he achieved AFAIK. You are probably right when we are talking about "more, more".
Do you think so? You need to keep in mind the hardware that Wirth did have and the goals that he wanted to achieve.
Yes I do think so and both Ada and C++ are successes too if the criterion is "they did what their inventors wanted to achieve".
I still believe that it was better than C++ and that is because C++ has so many features and the compile time is abysmal.
shrug The C++ of the 80ies and 90ies probably has fewer features than you imagine and the compile times of e.g. Borland C++ were acceptable.
Long compile times can also imply that the compiler does something complex like actually optimizing your programs (C++) or proving properties that are important for security (Ada).
Long compile times can also imply that the compiler does something complex like actually optimizing your programs (C++) or proving properties that are important for security (Ada).
I always figured that "in the future" compilers will take successive refinement approaches. The first pass would be fast and simple. Then a second level could run which prove code properties and/or do more expensive optimizations.
Basically the line between JIT and AOT would become more blurred. Of course Nim will be doing pre-cognitive quantum compiling by then. :p
While other Nim GUI are mostly unknown territory.
Unfortunately true. Though I've really enjoyed hacking away on Fidget & Fidgetty. There's lot of potential, but also lots of work and never ending details. I'd really like to be able to re-use the native text input boxes like the browsers (used to?) do. Text input handling is such a pain. :/
I experiment with such approach, something like Elixir Phoenix LiveView + React.JS in Nim , but eventually discarded it, as it's simpler to just use Svelte & TypeScript.
LiveView is fantastic! Well except for the web part. I think a library like that for Nim would be great.
Alternatively a Clojure style seemless front-end / back-end style library would be equally good. Though it seems one hasn't really taken off on the Nim front?
network latency is zero and bandwidth unlimited, so you can just mirror every single change and send back and forth between Nim Process and Web Browser every single event.
In theory, Fidget's rendering engine(s) and its user facing API could be split and the data sent over a binary protocol. Fidget essentially builds up a tree of dom-like nodes. They're simpler than dom nodes though so serializing them wouldn't seem to be infeasible assuming appropriate caching for images/fonts/strings.
I've toyed with the concept of doing that in Fidggety as a possible way to have a Nim(C) renderer and a Nim(VM) / Nim(JS) frontend for rapid development. It'd probably be possible to mock up in a weekend. Ok... a long 3 day weekend. ;)