The key premise of this approach is to provide a SwiftUI-like declarative wrapper around Gnome functionality. It's unclear what it adds over swift-cross-ui.
SwiftUI itself has growing pains mainly around being on the right thread for processing/updates and getting data binding right.
Blog entries on swift.org or from Apple tend to be little demos that show the happy path, but when discussing new frameworks (like a Gnome wrapper) or platforms (like the recent embedded), I'd like more demonstration that the authors understand and address key issues and will sustain development. Cross-platform UI frameworks get complicated quickly and have a long tail of issues (cf Flutter, Java/Eclipse, et al) that can be blockers for clients/users. For Swift it doesn't help to have multiple concurrency models and obviously different behaviors on apple platforms and Linux (where UI is not officially tested).
I’ve never struggled with being on the right thread. It’s always main to update UI. Grand dispatch makes this trivial, and the recent actors work also extends this. I’m also not sure how this is SwiftUI specific as UIKit and most other UI frameworks are the same. What are the growing pains here?
Aside from UI updates, processing includes view-model derivations (e.g., calculating errors), persistence, and loading, all of which are offloaded to dispatch queues or actors and then brought back to the UI/main thread. wrt granularity, there's @State, @StateObject, and @Observable, with different binding reaches. So understandably a lot of choices reflecting legacy and new API's, integration with UIKit and web/media services -- and probably AI recognizers in the background. To me the pains are that the approach taken needs to be consistent application-wide (async is pretty viral, queues are designed to be shared e.g., per subsystem, etc.), making it hard to manage or migrate a code base. Also many features build on macros which can make builds almost intolerable. Also saving on macOS vs integrating with update manager on iOS. It can be hard even to find documentation on stdlib feature support e.g., Regex. It's good they maintain both the legacy support and go full-steam-ahead on new features, but developers (i.e., I) need more guidance on tip-toeing around pitfalls and managing platform differences.
Well, I've been fighting with an extremely simple Navigationsplitview for ages. Put a list in the sidebar, put 100 items in it, and render almost anything else in the detail on macos (one version back). Then select an item in the nav and hit the down arrow.
Depending on implementation, scrolling will get clipped to the visible area, it'll hold onto multiple selections if the first has been scrolled off screen, or the main thread will get thrashed and performance will be about what the current settings menu is.
I haven't found something that I don't have to accept a really mediocre experience with, but next I'm going to try rewriting it with NSTable
Swift is such a delightful language to use, well suited for general application development. It's awesome to see it gaining traction outside of the cocoa ecosystem. If you haven't given it a fair chance yet, I would highly recommend you do!
Will have to try it to see how well it works in practice, but very cool. I can see this being popular for side project apps written by iOS devs that otherwise wouldn’t have an Android port.
Which ended up having such a community backslash that Miguel de Icaza decided to focus his efforts on Xamarin instead, followed by Microsoft's acquisition, and nowadays he is focused on Apple's ecosystem, Swift and Godot on Apple platforms.
While I found the MonoProject interesting, I was skeptical using it. Sure, it is an Open Source .NET framework but .NET is Microsoft at the end of the day. I do not (and still do not) want their fingerprints inside my GNU/Linux machine.
What I mean by this is the legalities behind it.
Remember, my comment above is based on views 20 years ago. My perspective is that Microsoft cannot "beat" Linux purely as competition. It isn't going anywhere. While it may not be a concern in the Desktop market, it certainly dominates on servers! Microsfot are not stupid and see CONTROL through other means.
Imagine if most programs that come default in Linux distributions being C#? If more and more programs are written in C# (whether Mono or not) gives them power over the Linux user.
Today, Microsoft has .NET core (recent release .NET 8) and also replaces Mono. We still have Xamarin of course but that is getting replaced with MAUI. A lot of Microsofts software is now cross platform, like Powershell, SQL Server, etc. This "concern" I was having 20 years ago is still just as big of an issue today.
Imagine Microsoft getting the marketing right and SQL Server starts gaining momentum on Linux boxes. This means less using MySQL or Postgres.
Imagine is Powershell starts gaining more traction in Linux land rather than Bash.
Now -- I think this is EXTREMELY UNLIKELY to happen but you can garantuee this is a strategy. They have the money and manipulation skills to help make it happen. Big companies can easily eat this up and it starts with "but we can support you!"
Think about it -- WSL is easy to setup on Windows machines! More and more C# applications can easily be tested for Linux. Microsoft just gave you the tools, and letting developers/companies do the rest for them. Soon it is sheep follow sheep.
Bit of a long winded comment/reply - and while I do not share targeting hate towards anyone (I do not know Miguel personally but he seems like a cool guy) -- I just think efforts should have been elsewhere. Dlang could have been a really, really good replacement. My guess as to why Dlang didn't take off back them was the compiler was not open source. Who knows?
I feel like a cross platform Swift GUI would be a great thing for the world. Swift strikes a great balance between ergonomics and performance, and seems to be the only other mainstream language to have absorbed some of Rust's key features around borrowing references.
For the record, borrowed references are only going to be really usable in Swift 6 which isn't released yet.
That said, Swift's implementation of borrowing seems significantly more user-friendly than Rust's. While this is very much an advanced feature, I'd expect it to be actually used in many cases where in Rust folks would resort to working around the borrow checking (via things like indexing into arrays and such). As a result I expect it to be significantly more useful.
Browser Company sort of built this themselves for Arc, but its really a separate SwiftUI-like Windows implementation (Windows UI is separate code written in a similar style). It still feels like a technical preview though unfortunately.
I recently wrote a small side project using vala + gtk4.
I tried blueprint, and while I liked the format, I struggled with a lack of documentation on how to do some more advanced things. Gtk's .ui files are ok, but you still end up writing a lot of code to hook everything up.
While I really like vala as a language, I think it'd be great to write all my logic and models in vala, then use this swift library for the UI.
In the context of Gnome/GTK development, there's almost nothing more stable and comprehensive than Vala, as it's been around a very long time and was created specifically to occupy that space. Can't speak for OP about why to combine it with Swift handling the UI, but certainly Vala still has far better support for the Gnome data model and APIs outside of those specific to the GUI.
Writing UI code layouts is suboptimal in any language. Delphi had it right - place whatever controls you like in a GUI, set up basic behavior via properties, then just quickly write handlers in code.
Perhaps, but as a counterexample, the SerenityOS people implemented the Delphi approach with Visual Builder but then realized that they preferred working with text, so they replaced it with a declarative DSL and live preview (GML Playground).
I don't know about Visual Builder, but judging from this screenshot[0] it doesn't look like the Delphi approach, but the "Windows resource editor" approach. Yes, both allow you to place things visually, but one works with live instances of serialized objects in an IDE that also understands the edited source code and can modify the code to -e.g.- introduce a new event handler for the OnClick event when you doubleclick the button (even with the cursor placed just right where you can start writing the actual logic of the event handling code), while the other has you draw the UI, assign some IDs and then expects you to do all the plumbing of loading the UI, associating it with code and handlers by hand.
The difference might sound trivial but in practice it is like trying to dismiss editing text with Emacs by experiencing editing text in Notepad.
I also admire the simplicity of this approach, but it has several downsides:
- Code-based UIs tend to work better with existing tooling, like comments and source control. You can freely customise your development environment, rather than being at the mercy of a single GUI app.
- Most serious UIs need code-like features, such as "for-each" to render a list of objects, or "if" to reveal a form when a checkbox is ticked. The easiest way to access code-like features is to write your UIs in code.
- You'll need to write some backing code in any case. Defining the UI tree and its "code-behind" in the same file could be considered more DRY.
- Live preview (or alternatively, hot reloading) will give you very quick iteration when writing a UI in code. It's not quite as good as drag-to-resize, but it's close.
- Automatic layout (which is non-optional nowadays) isn't necessarily a great fit for WYSIWYG editing.
- As React has demonstrated, the ability to quickly throw together custom components is extremely useful. Visual editors tend to make it more complicated and bureaucratic to define custom components.
- WYSIWYG editors are bad about making small unintended changes that can easily slip by undetected (Interface Builder in Xcode for example often changes XIBs/storyboards just by viewing them)
- WYSIWYG editors bury bits of configuration in inspectors that are only visible in certain conditions, e.g. a control being selected, making them less evident and more difficult to find
There are circumstances where I think they still work alright — for instance I still enjoy building Mac apps with XIBs in Cocoa, but there’s a reason for that: traditional desktop UI has much less of a need for flexibility and generally speaking, has far fewer moving parts since it doesn’t have to hide things as a result of limited screen real estate. Additionally, these apps will only ever run on Macs which further reduces need for flexibility/adaptivity.
For mobile and multiplatform on the other hand, I strongly prefer code. It just works better.
My immediate though of the Swift Example Code was "but where does the business logic go".
This trivial example lacks it, and places it simple logic inside the UI code. But what if we want to protect against negative numbers? Or want to increase the number with larger increments if we hold the button pressed? Etc.
Your Delphi setup isolates business logic from UI. Which may seem "overly complex" in trivial demoes, but will help you the very moment you write the first test or add some business logic.
It's also why I see so many React apps spiral into an unmaintainable mess within days after their "git init".
> Your Delphi setup isolates business logic from UI. Which may seem "overly complex" in trivial demoes, but will help you the very moment you write the first test or add some business logic.
But then what if the UI changes dimensions? Then you'd need an underlying set of rules, and isn't it best if you can set those rules yourself? How would that work graphically?
And then how about version control? Sure there could be (and is) underlying machine code, and you could try hard to make it human readable. But... IDK seems like a lot of effort to me for some small benefits.
Disclaimer: I have only very little experience with UI programming.
> But then what if the UI changes dimensions? Then you'd need an underlying set of rules, and isn't it best if you can set those rules yourself? How would that work graphically?
I don't know about current Delphi, but in Lazarus (which is kind of an open source and crossplatform Delphi) you set those rules visually. For example you can "draw" the UI by drag-and-dropping controls in a window/containers/etc and then you can add rules like "this button's left side will be 5 pixels from that label's left side and will be placed vertically so that it is centered relatively to the label". You can also set things like "this control (or container or whatever) will always be at the top/left/right/bottom edge of its window/container". This is done in the visual editor with immediate feedback (you can even resize the window/container while you are editing its layout to see how it behaves).
This allows you to make UIs that work not only across dimensions, but also handle different fonts, texts (for localization), scaling (for DPI) and themes. Especially important for Lazarus since its GUI framework has various backends that often look very different from each other.
> And then how about version control?
Lazarus (and Delphi - with the exception of some earlier versions - and really most GUI designers) save UIs in a text based format with a tree-like structure of key/value pairs, e.g. (i edited it a bit for brevity):
object Main: TMain
Left = 625
Height = 505
Top = 393
Width = 903
Caption = 'World Editor'
Menu = MainMenu1
Position = poScreenCenter
object plRenderContainer: TPanel
Align = alClient
BorderStyle = bsSingle
object plRenderWindow: TPanel
Align = alClient
BevelOuter = bvNone
end
end
end
This can easily be stored in version control and diffed to see changes (in fact in my own projects before committing something to VCS i check both the code and the UI files to see what exactly i changed).
> But then what if the UI changes dimensions? Then you'd need an underlying set of rules, and isn't it best if you can set those rules yourself? How would that work graphically?
Look into how various design tools handle flexible layouts. Usually a combination of flexbox/something similar to flexbox or slightly more old-school; constraints.
You solve this by using a layout control (a UI control specifically for managing the size/position of its child controls). For example using a visual form builder you could drag-n-drop a "vertical layout control" and then drag-n-drop controls inside it to be resized/positioned in a vertical stack.
The window itself can have a layout control that stretches to fill the window regardless of resizing. Layout changes would cascade down through the tree of UI controls and everything would resize/reposition accordingly.
That's what mac/iOS development has had since before it was even mac, back in the NeXTStep days... But it doesn't work very well for very custom stuff.
Generally writing UI code in Xcode (and presumably before that on NeXT as well) is a breeze and a joy. Work with your delegates, connections, outlets etc.
It is the same approach as declarative UI programming like SwiftUI or QML, but with an extra GUI abstraction on top of it. An artifact of this GUI-driven development process (like Xcode or Glade) is still a file with some declarative markup (sometimes even human-readable).
> An artifact of this GUI-driven development process (like Xcode or Glade) is still a file with some declarative markup
Not really in the case of Cocoa's Interface Builder (nib/xib files). There the artifact is basically a marshalled object tree of the actual UI objects, not declarative markup.
There is a big qualitative jump when one can arrange and play with UI without writing a single line of code, even if the user's decisions about component placement are recorded in a declarative file.
The old fashioned screwdriver has it right. Why fiddle with charging batteries, using a chuck and selecting direction when you can just pick up a ol’ screwdriver and get going!
… assembles an appartments worth of new Ikea furniture…
Try Delphi/Lazarus for just 10 minutes, then come back with a better metaphor. The productivity difference in comparison to React, Qt, GTK etc. is enormous. When was the last time you built the whole UI of a large app in 1 day?
It is not. macOS/iOS had it for a long time with AppKit, UIKit. But the progression is usually this: you start with Interface Builder and storyboards or .xibs, then you see the problem with that and gradually move to code-only UI and then start looking at SwiftUI with it's declarative UI like a guy in that meme.
GUI for layout just does not cut it, especially when your app runs in very different environments - it can be macOS, it can be a phone or just a smartwatch/widget.
I believe the references to “arc” here and elsewhere in the thread is referring to the new web browser and not the Lisp-family language. There’s a GitHub link to a Swift ui bindings for Windows elsewhere by another poster here.
The key premise of this approach is to provide a SwiftUI-like declarative wrapper around Gnome functionality. It's unclear what it adds over swift-cross-ui.
SwiftUI itself has growing pains mainly around being on the right thread for processing/updates and getting data binding right.
Blog entries on swift.org or from Apple tend to be little demos that show the happy path, but when discussing new frameworks (like a Gnome wrapper) or platforms (like the recent embedded), I'd like more demonstration that the authors understand and address key issues and will sustain development. Cross-platform UI frameworks get complicated quickly and have a long tail of issues (cf Flutter, Java/Eclipse, et al) that can be blockers for clients/users. For Swift it doesn't help to have multiple concurrency models and obviously different behaviors on apple platforms and Linux (where UI is not officially tested).
Depending on implementation, scrolling will get clipped to the visible area, it'll hold onto multiple selections if the first has been scrolled off screen, or the main thread will get thrashed and performance will be about what the current settings menu is.
I haven't found something that I don't have to accept a really mediocre experience with, but next I'm going to try rewriting it with NSTable
https://github.com/stackotter/swift-cross-uihttps://github.com/TokamakUI/Tokamak
I’m also working (slowly) on native Flutter channels:
https://github.com/PADL/FlutterSwift
But this is really targeted at embedded use cases.
[0] https://github.com/sony/flutter-embedded-linux
Do any of these have a good wkwebview equivalent
"Miguel de Icaza and his ostracization from FOSS" https://www.linux-magazine.com/Online/Blogs/Off-the-Beat-Bru...
"What killed the Linux Desktop" https://tirania.org/blog/archive/2012/Aug-29.html
"How I ended up with a Mac" https://tirania.org/blog/archive/2013/Mar-05.html
One might wonder how things would have turned out instead if the community had been more welcoming of his efforts on GNU/Linux.
What I mean by this is the legalities behind it.
Remember, my comment above is based on views 20 years ago. My perspective is that Microsoft cannot "beat" Linux purely as competition. It isn't going anywhere. While it may not be a concern in the Desktop market, it certainly dominates on servers! Microsfot are not stupid and see CONTROL through other means.
Imagine if most programs that come default in Linux distributions being C#? If more and more programs are written in C# (whether Mono or not) gives them power over the Linux user.
Today, Microsoft has .NET core (recent release .NET 8) and also replaces Mono. We still have Xamarin of course but that is getting replaced with MAUI. A lot of Microsofts software is now cross platform, like Powershell, SQL Server, etc. This "concern" I was having 20 years ago is still just as big of an issue today.
Imagine Microsoft getting the marketing right and SQL Server starts gaining momentum on Linux boxes. This means less using MySQL or Postgres.
Imagine is Powershell starts gaining more traction in Linux land rather than Bash.
Now -- I think this is EXTREMELY UNLIKELY to happen but you can garantuee this is a strategy. They have the money and manipulation skills to help make it happen. Big companies can easily eat this up and it starts with "but we can support you!"
Think about it -- WSL is easy to setup on Windows machines! More and more C# applications can easily be tested for Linux. Microsoft just gave you the tools, and letting developers/companies do the rest for them. Soon it is sheep follow sheep.
Bit of a long winded comment/reply - and while I do not share targeting hate towards anyone (I do not know Miguel personally but he seems like a cool guy) -- I just think efforts should have been elsewhere. Dlang could have been a really, really good replacement. My guess as to why Dlang didn't take off back them was the compiler was not open source. Who knows?
I remember making some rudimentary accounting software for which I'm sure now the source is long gone.
https://www.nuget.org/packages/GtkSharp
That said, Swift's implementation of borrowing seems significantly more user-friendly than Rust's. While this is very much an advanced feature, I'd expect it to be actually used in many cases where in Rust folks would resort to working around the borrow checking (via things like indexing into arrays and such). As a result I expect it to be significantly more useful.
I tried blueprint, and while I liked the format, I struggled with a lack of documentation on how to do some more advanced things. Gtk's .ui files are ok, but you still end up writing a lot of code to hook everything up.
While I really like vala as a language, I think it'd be great to write all my logic and models in vala, then use this swift library for the UI.
At that point, why not just do everything in Swift? What does Vala give you that Swift doesn't?
Here's Andreas Kling briefly demoing both and talking a bit about it: https://www.youtube.com/watch?v=1QYBvTy9QKE&t=519s
The difference might sound trivial but in practice it is like trying to dismiss editing text with Emacs by experiencing editing text in Notepad.
[0] https://adkaster.github.io/images/build/VisualBuilder.png
- Code-based UIs tend to work better with existing tooling, like comments and source control. You can freely customise your development environment, rather than being at the mercy of a single GUI app.
- Most serious UIs need code-like features, such as "for-each" to render a list of objects, or "if" to reveal a form when a checkbox is ticked. The easiest way to access code-like features is to write your UIs in code.
- You'll need to write some backing code in any case. Defining the UI tree and its "code-behind" in the same file could be considered more DRY.
- Live preview (or alternatively, hot reloading) will give you very quick iteration when writing a UI in code. It's not quite as good as drag-to-resize, but it's close.
- Automatic layout (which is non-optional nowadays) isn't necessarily a great fit for WYSIWYG editing.
- As React has demonstrated, the ability to quickly throw together custom components is extremely useful. Visual editors tend to make it more complicated and bureaucratic to define custom components.
- WYSIWYG editors are bad about making small unintended changes that can easily slip by undetected (Interface Builder in Xcode for example often changes XIBs/storyboards just by viewing them)
- WYSIWYG editors bury bits of configuration in inspectors that are only visible in certain conditions, e.g. a control being selected, making them less evident and more difficult to find
There are circumstances where I think they still work alright — for instance I still enjoy building Mac apps with XIBs in Cocoa, but there’s a reason for that: traditional desktop UI has much less of a need for flexibility and generally speaking, has far fewer moving parts since it doesn’t have to hide things as a result of limited screen real estate. Additionally, these apps will only ever run on Macs which further reduces need for flexibility/adaptivity.
For mobile and multiplatform on the other hand, I strongly prefer code. It just works better.
This trivial example lacks it, and places it simple logic inside the UI code. But what if we want to protect against negative numbers? Or want to increase the number with larger increments if we hold the button pressed? Etc.
Your Delphi setup isolates business logic from UI. Which may seem "overly complex" in trivial demoes, but will help you the very moment you write the first test or add some business logic.
It's also why I see so many React apps spiral into an unmaintainable mess within days after their "git init".
This is true for any library/framework/architecture, and the same problem is very prominent in Svelte/Vue/React/Backbone/Angular and everything else.
So basically, the same as Cocoa/obj-C?
And then how about version control? Sure there could be (and is) underlying machine code, and you could try hard to make it human readable. But... IDK seems like a lot of effort to me for some small benefits.
Disclaimer: I have only very little experience with UI programming.
I don't know about current Delphi, but in Lazarus (which is kind of an open source and crossplatform Delphi) you set those rules visually. For example you can "draw" the UI by drag-and-dropping controls in a window/containers/etc and then you can add rules like "this button's left side will be 5 pixels from that label's left side and will be placed vertically so that it is centered relatively to the label". You can also set things like "this control (or container or whatever) will always be at the top/left/right/bottom edge of its window/container". This is done in the visual editor with immediate feedback (you can even resize the window/container while you are editing its layout to see how it behaves).
This allows you to make UIs that work not only across dimensions, but also handle different fonts, texts (for localization), scaling (for DPI) and themes. Especially important for Lazarus since its GUI framework has various backends that often look very different from each other.
> And then how about version control?
Lazarus (and Delphi - with the exception of some earlier versions - and really most GUI designers) save UIs in a text based format with a tree-like structure of key/value pairs, e.g. (i edited it a bit for brevity):
This can easily be stored in version control and diffed to see changes (in fact in my own projects before committing something to VCS i check both the code and the UI files to see what exactly i changed).Look into how various design tools handle flexible layouts. Usually a combination of flexbox/something similar to flexbox or slightly more old-school; constraints.
Here is an example with Figma: https://gdwn.medium.com/how-you-can-create-really-flexible-a...
The window itself can have a layout control that stretches to fill the window regardless of resizing. Layout changes would cascade down through the tree of UI controls and everything would resize/reposition accordingly.
Generally writing UI code in Xcode (and presumably before that on NeXT as well) is a breeze and a joy. Work with your delegates, connections, outlets etc.
Not really in the case of Cocoa's Interface Builder (nib/xib files). There the artifact is basically a marshalled object tree of the actual UI objects, not declarative markup.
… assembles an appartments worth of new Ikea furniture…
Oh!
But the question here is also if it makes sense to basically have the same UI or even UI paradigms for such different types of environments.
> On top of this example I’d add Arc for macOS and Windows.
Didn't development of Arc stop like a really long time ago? Anarki seems to be where development is at nowadays.
[0]https://arc.net/