VisualStudio Code on Haiku

I see another use-case for GUI markup. When your application is cross platform and you want to keep its GUI code native for each platform. Any application author will be interested in as many platforms as possible. And usually the GUI part of application code is rather large.

Now, imagine you want to extend the GUI. If you just write GUI code in target language, you will make as many coding changes as many different platforms your application has. And, because the users expect application consistence across all the platforms you need to ensure this by manual checking.

On the other hand, having a standard GUI markup and code generators for each GUI API, your modifications are all in one place, and the cross-platform consistence is guaranteed.

4 Likes

I mostly do Android these days, and the UI designed has never really worked. They gave up and made Hot Reload. That is now the preferred route, even for WPF. Hot Reload is basically shipping the changes on the fly, so it means the UI is running on a real device/emulator running the target OS.

Having a way to separate the UI code from the business logic is very important, and makes the UI reusable, testable and replaceable without completely gutting the code. Componentizing app code is very powerful.

3 Likes

Re:GUI optimization
It looks like I might not invest the time for an SVG diagram after all, but I do have a word picture that can illustrate what my proposal is: Imagine all of the static buttons and other static clickable objects as being contained in the cells of a spreadsheet. Their alignment would be determined by the widths of the rows and columns of that spreadsheet. The advantage is that coordinates that align need to be recomputed during a resize operation only once and the row and column structure changes are unaffected by a resize. Ultimately, however, to get to the point of the rows and columns being the convergence of multiple clickable objects would require a domain-specific language to convert the discrete object definitions into the irregular grid form. This would reduce the runtime complexity of the GUI at the expense of the compilation optimizations. Modularity would also be shifted from runtime to shared objects loaded into the GUI compiler.

You mean like:

<Grid RowDefinitions="*,*,*" ColumnDefinitions="*,*,*">
  <Button Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Text="Click 1" Command="{Binding Click1}"/>
  <Button Grid.Row="1" Grid.Column="0" Text="Click 2" Command="{Binding Click2}"/>
  <Button Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Text="Click 3" Command="{Binding Click3}"/>
  <Button Grid.Row="1" Grid.Column="2" Text="Click 4" Command="{Binding Click4}"/>
  <Button Grid.Row="2" Grid.Column="0" Text="Click 5" Command="{Binding Click5}"/>
  <Button Grid.Row="2" Grid.Column="2" Text="Click 6" Command="{Binding Click6}"/>
</Grid>

Which looks like this:
image

You don’t need to reinvent the wheel. Also - what you are talking about, the low level composting, has nothing to do with the mark-up. The mark-up just describes to the resource compiler/loader how to arrange the controls. What you are talking about is very low level and would be in the AppServer or something like that. That stuff is not really the remit of the UI components. The theory is, you could completely change the renderer and the UI would still be rendered like that.

And for @dragon, no UI was designed using design time viewers… I just typed that code in by hand and ran the app under Windows.

1 Like

You’re exactly right @memsom. There is no reason to reinvent the wheel. My observation is that the old HTML3 table layouts were sufficient without modern frameworks and could do the job without much new implementation. Being able to simplify modern gadgets to their table/grid layout equivalents would make the GUI libraries smaller because there would only need to be a table/grid layout for every gadget type. My example was going to be how a file requester dialog could be implemented in a grid with 3 sub-grids for the 2 sliders and one for the scrolling listview. That beats having to have separate layout code for each gadget, in my thinking.

My implementation would involve custom lowering as LLVM does in its backend. That’s why I thought a compiler would be the best way. The type of compiler could be an AOT compiler within the layout kit code though, saving some compatibility.

You don’t want HTML, no sensible UI for a desktop application is done in HTML because HTML is a really terrible UI mark-up outside of basic stuff. It is based around a form based metaphor. Any UI mark-up should be extensible and open. The web and HTML should not touch desktop. Rendering HTML well is not fun.

As I hope I showed, most modern UI is done with constraints these days, so I really don’t see the advantage of HTML.

Constraint based layouts are the norm these days. They do what you suggest and can adjust and resize to the canvas available. Nothing about what you are saying is particularly new or innovative. Haiku even has a way to do it already, with the example @leavengood gave above.

That sounds way over complicated. You don’t need all that. The ListView just needs to sit in a ScrollView.

I think the issue with what you want is that you want to rewrite the UI toolkit. I don’t. I don’t even want to massively adapt it. I just want a way to serialise the UI to a markup, and deserialise it back to an instance of a BWindow. The BeAPI is not up for being replaced, it’s the native toolkit.

At the end of the day, this all needs to be deconstructed to UI code, and for Haiku, that is a BWindow containing BViews. It sounds like you want something else, and I don’t really think it is what Haiku needs. If this is about WebAssembly again, I think the WebAssemply needs a way to use the BeAPI, including the UI toolkit. If it lacks that, it is pretty useless.

2 Likes

Actually I hate constraint based systems since they make the most simple layout problems awfully complicated and error prone. I’ve dealt with various constraint based UI systems and they all are a pain to set up and maintain.

1 Like

So the alternative is…? Pixel perfect rendering is really not much fun. Especially without a designer. Seriously, running your code multiple times to tweak some control by a few sub pixels sucks. The BeAPI has a floating point coordinate system, so you can move things by sub pixels (as in, it looks the same) which is fine, but on high DPI, the sub pixels start to become important as you scale the UI.

Manually aligning UI in code is for masochists… this is coming from someone who wrote a UI toolkit for rendering complicated UI in an Android app, and regretted it enough to convert it all to layout based. Because moving controls around pixels at a time in code is really just for people who hate sensible code. At the time, rendering the data from 30 devices with complex UI requirements seemed like some simple code and Skia would be fine. Render the data to a canvas, all good. No. It ends up being unmaintainable. Because re-doing the UI is hell. Add in more data, basically tear out your hair. Even that UI used a grid based offset system which allowed for floating point offsets, but had to use tricks to make mapping stuff out a lot easier by showing boundary boxes and grid lines to help visualise.

The benefit of constraint based layout is, you can get the basic layout in place and the tweaking is just a case of setting constraints, not moving controls 1 pixel at a time to balance the layout.

2 Likes

You got me wrong. I don’t like “constraint” based systems not “layout” based systems. They are “not” the same (albeit similar), although some might think so. Constraints are pain… layouts not (if done right).

A layout system is a constraint based system, it just has a nicer API

1 Like

Layouts are dynamic, constraints are static. This makes constraint based systems such a pain to work with since you have to hand-place and wire every single widget and yet it still fails for dynamic screen layouts outside simple cases. HTML would be a layout system but whoever designed it has been a masochist (hence why I said “if done right”)

What does this mean? Could you explain it for a simple minded person?

I work with CAD programs where constraints are really useful, but setting up the constraint-system is time consuming and 2D constraint solvers can be painfully slow. After ~15 years professional work i belive allmost all problems related to constraints (in my field) is simply user error. Naive solutions proved to fail in the most interesting ways and from my experience ~95% of CAD users are not capable to abstract thinking. (BREPs are a b*tch to work with, and while it is allowed and possible, you are not supposed to use any BREPs for constraining. Sadly all the training material starts with “let’s use BREPs”.) I am a CAD trainer and lately thinking about writing a book about this topics.

I assume a similar PEBKAC going on with gui layouting. Remember: “We cannot solve our problems with the same thinking we used when we created them.”

Thank you.

I don’t know anything about html but this is not true. A stack UI container that is set to fill the parent object (let’s say a window) is constrained to have its width and height equal to the window width and height. Three child elements in the stack set to share the space are constrained such that their width is equal to the width of the parent object (the stack, and thus the window) and their height is set to a third of the stack height, and thus a third of the window height. Changing the window size will dynamically change the sizes of each element based on the constraints set by the layout.

Entirely constraint based systems such as haikus own Auckland layout system simply allow you to create constraints directly instead of using layouts, for example element left side = window left side and element right side = window right side, which is the same as a layout where the element is set to fill the horizontal space. In this case resizing the window will still change the size of the ui element dynamically.

I think you must be talking about something slightly different.

Constaint systems are static because you have to hard-wire the constraints for each and every widget in the UI. This process is time consuming, error prone, creates static relationships you can not change at runtime anymore (or only painfully) and the layouts react clumsy to size changes of the container since the constraints are static in nature and rather dumb. As mentioned chances are high adding a new widgets makes your constraints go haywire leaving you trying to fix the mess for hours (been there done that multiple times. in the end I had to git reset/checkout to start anew since no amount of stackoverflow-fu helped)

Layout systems are dynamic since they have no hard-wired constraints but instead work with rules that apply to all widgets in the container at the same time. This allows layout systems to be fully dynamic at run-time. They can easily adapt to changing sizes including altering widget placement to achieve the best results. They are easy to use and resiliiant against errors.

A good example of why constraint systems suck is the iPhone layout engine (attention! a “layout engine” can use a “constaint system” or a “layout system”). If you ever tried to get a meaningful UI together with that system you are close to end up in a nuthouse. Now constraint systems try to mitigate their suckiness by adding “layout widgets”. These are dumbed down small layout systems which try to add the superiority of layout systems into a constraint system. This works in the small and limited layout capabilities they provide but instead of trying to work around a broken system they should ditch constraints and switch over to a layout system in the first place for the sanity of the developers and users.

Thanks for the explanation.

This however feels like none of this 2 way is superior.
What could be a third way?

While what you are saying may be true, you are not using static and dynamic in the normal sense of the terms with respect to programming languages. Static is something defined or inferred once at compile time, e.g. object.width = 10, dynamic means that it changes or is inferred at run time and may change during execution.

In the systems you describe the only difference is that the API for adding an element to a container adds the constraints for you, where in a purely constraint based system you have to create all the constraints manually. They are both dynamic. Which leads back to my initial point… That a layout system is a constraint system with a nicer API.

I don’t think so. I use static and dynamic here in the context of UI design not programming so in my opinion there is a large difference. As you mentioned if you want to add a widget at run-time with a constraint system you have to manipulate the constraints (sometimes of all widgets). This can easily become very complicated and you have to have knowledge about the layout engine and how to manipulate it. So in my opinion a layout system is not a nicer API for constraints since you do not define (nor have access) to constraints nor do you have any idea (nor do you have to know) about how the layout engine works.

That layout systems are based on constraints is not my opinion, it is just the way it is. If you change “constraint based” to mean something other than “implemented using constraints” then yes, you can make different claims.

If you look at the haiku layout implementation, e.g. https://github.com/haiku/haiku/blob/master/src/kits/interface/TwoDimensionalLayout.cpp, it is entirely based on constraints.

The constraint solvers themselves are in https://github.com/haiku/haiku/tree/master/src/kits/interface/layouter

Thus, the haiku layout system is a nice API over a constraint based system.

That the API is different and you don’t have to manipulate constraints directly is exactly why it is nicer. I agree that coding constraints directly is a pain and makes life very difficult. It doesn’t change the fact that, to quote my original message, “A layout system is a constraint based system, it just has a nicer API”. I agree that layout based APIs are much better than constraint based APIs.

1 Like

If it’s just a wrapper for adding/removing constraints manually then in I think it is not a layout system but a constraint system with a utility layer over it. In my opinion (and that’s how I implemented it in Drag[en]gine) a layout system does not wrap a constraint system but uses other techniques, which typically are easier to understand, more efficient and more performant. But I guess you can implement a layout system over a constraint system if you really want to.

@dragon Can you maybe give an example of a layout system you have used and you feel is good? I am struggling to see the difference.

I generally (as I said above) use Xaml, and the constraint system in Xaml is really simple. You align horizontally and vertically and then you either give “auto” or “*” for the columns and rows in grids, unless you want to force something more static, then you can specify percentages or absolute values. The way the UI flows is easy to predict and I don’t spend much time on it, except when a screen design was not conceptualised by the designer to be constraint based. Because a lot of the items in the UI are templated, you also only need to design that once.