Maybe I jumped the gun. I’m not an expert on GUI programming. In what case do thousands of GUI callbacks need to be called in one second? I would be interested to know.
The example only goes through the code once and then enters a GUI loop and also uses callbacks, so ... yeah. Doesn't look like immediate mode GUI to me.
Typically we build GUIs using event driven callbacks. This causes problems in managing life times, dynamic layouts, threading issues etc. The idea behind immediate mode GUI is that you get a frame and in each frame you create/update layout, check for user actions - just like you do in render frame in game loop. So there are no call backs and you don't have to worry about issues arising from event-driven code.
I'm having a hard time guessing the details of how a GUI that doesn't have an event loop in it would work, so I think a more detailed answer would be very interesting.
Handling concurrency should be an accepted part of the skill set of GUI development.
Writing a user interface that can respond to user input, whilst also being able to handle and respond to a long running data access or computational requests is a concurrent problem.
Having a single threaded model with callbacks, like the JavaScript browser model is one of the less complex ways to handle this.
I agree that a less complex model is appropriate for some developers/applications. But to call yourself a "skilled-professional GUI-developer", you need to get awesomely brilliant enough to handle this.
Typically GUI work is instantiated with the GUI toolkit on the call stack. It calls foo.onClick(), etc. Now, if one particular onClick starts long-running task, then there are three possible designs:
Either that particular onClick() starts a worker thread and returns before the worker is done.
Or the GUI toolkit delivers the onClick() in a thread of its own, e.g. from a pool of workers.
Or everything is done in one thread, and the UI blocks.
The last one seems sucky, but the insidiously sucky one is the one in the middle. That's where every user's implementation of onFocusOut() must take care to lock because all of bar.onFocusOut(), foo.onFocusIn(), foo.onMouseUp() and foo.onClick() are called concurrently in four different worker threads. The tail wags the dog.
The core of a GUI framework is nearly always written as asynchronous events and drawn responses, with the developer at that level responsible for the state machine in the middle and invalidation of the GUI in response.
Coordinating large asynchronous systems by hand is challenging. There can be surprising interactions. For example, tapping a button again in the middle of an animation is an example of something where the complexity often leads to the program getting in a bad state or even crashing.
This is one reason that structured concurrency and asynchronicity primitives have been added to many programming languages - to make reasoning about and managing such state machines easier.
Some modern GUI frameworks attempt to simplify this by instead let you declare the UI and its relationship with your data, the interdependencies there, and may have sophisticated means to monitor data changes. This breaks you from having to maintain most GUI state within your program - you respond to user actions by updating your program state, and the GUI responds to those updates.
Yes I am especially curious to know how they manage state in desktop GUIs - if it's events and callback based or some other kind of functional architecture
While it's possible to write a Swing application that runs fast (starting fast is a different matter), it takes quite a bit of effort to do so, because the basic tools that it provides lead you towards slow applications and a lot of boilerplace.
Any shop that ever did a bunch of Swing and cared about quality ended up writing their own layer on top of Swing that made those features easier to use, but they still require quite a bit of discipline.
UIs is the kind of place where the whole reactive model actually works well. Create events, subscribe to events, and make each event handler run asynchronously. Use the dispatch thread for events that actually modify frontend-facing, elements, and everything else on background pools.
So the broadly available toolset could only be used well by programmers that are better than the typical guy that was asked to write the UI, and we never got better tools.
All GUI frameworks hide a lot of what’s happening in the insides. There is a scale to it but personally I think that reasoning about a “reactive” program is quite easier than untangling a ball of callbacks written in say, GtK.
Reactive frameworks indeed hide a lot of complexity but that does have positive impact on the user code. (IMO)
I am interested in immediate mode GUIs but I think we need a different paradigm for GUIs that is less synchronous from a user perspective.
Encoding behaviour in GUI code is complex due to state management and complexity. See jQuery.
In most GUIs as a user you do an operation and wait for it to complete (direct manipulation). You can't queue operations unless you code. I haven't seen macro recording done well.
I'm surprised immediate mode guis have taken such a long time to take hold. The separation of data and drawing in very elegant after having come from ui systems where your widgets essentially end up being data structures.
But sometimes the GUI implements part (or just possible all) of the functionality. A clever GUI design can simplify a complex user operation to the point where the "back end" is left to just read and write data.
It's not all about writing API's although (to be fair) this post makes some valid points.
i think the nature of GUI programming hasn't been well enough characterized, and thus the tools we use for building them aren't adequate. it's a bit like trying to do DB programming before transaction, and relational algebra were invented.
Gui has a lot of conceptually complex properties :
- it has both synchronous and asynchronous behaviors ( drag vs trigger an animation or loading data for the next screen )
- it has i/o (the screen)
- it is interactive (a user can click at any point in time, interrupting the process)
- it has transactional properties (you sometimes want a whole set of changes to be performed atomically, with nothing interrupting it).
-it is working both in diff mode ( change just the color of that button) and in whole state change (load a new screen)
Does this pretty-much rule out (without a huge amount of effort) nonmodal GUIs? It seems without callbacks, you would need to roll your own window management, Z-ordering of overlapping UI elements, state transition validation (e.g. clicking on the parent dialogue’s Cancel button while a child window is still open), ...
reply