Generate UI in code

Inspired by Daves’s great looking calculator… I tested building UI for a simple calculator program using 8th. Supports only the very basic calculator stuff and uses default Nuklear widgets, so it’s not too pretty.

I would love to see SwiftUI version…

calc

\ Calculator demo

needs nk/gui

32 constant FONTHEIGHT
1.2 FONTHEIGHT n:* constant ROWHEIGHT

FONTHEIGHT font:system font:new "font1" font:atlas! drop

: new-win
  {
    name: "main",
    wide: 240,
    high: 250,
    bg: "white",
    title: "Calculator"
  } nk:win ;

: +n \ nk n --
  >r 
  "num" nk:m@ 10 n:*
  r> n:+ "num" swap nk:m! ;

: mathop \ nk w -- nk
  "op" swap nk:m!
  "num" nk:m@ "a" swap nk:m!
  "num" 0 nk:m! ;

\ calculator display
: display
  "num" nk:m@ 0 ?: >s 32 nk:EDIT_SELECTABLE nk:EDIT_CLIPBOARD n:bor nk:PLUGIN_FILTER_FLOAT
  edit-string drop >n "num" swap nk:m! ;

\ calculator keys
: keys
  nk:widget if
    { rows: 4, cols: 4, rgap: 4, cgap: 4, margin: 4 } nk:layout-grid-begin
      \ the button labels:
      [ "7", "8", "9", "+" ,
        "4", "5", "6", "-" ,
        "1", "2", "3", "*" ,
        "C", "0", "=", "/" ]
      ( \ nk n s
        swap dup >r \ save the button index
        4 n:/mod swap 1 tuck nk:grid nk:rect>local nk:grid-push \ handle grid layout
        ( \ act based on what the index is
          r@
          [ ( 7 +n ) , ( 8 +n ) , ( 9 +n ) , ( ' n:+ mathop ) ,
            ( 4 +n ) , ( 5 +n ) , ( 6 +n ) , ( ' n:- mathop ) ,
            ( 1 +n ) , ( 2 +n ) , ( 3 +n ) , ( ' n:* mathop ) ,
            ( "a" 0 nk:m! "num" 0 nk:m! ) , ( 0 +n ) , ( "eq" true nk:m! ) , ( ' n:/ mathop ) 
          ] case
          "eq" nk:m@ if
            "eq" false nk:m!
            "op" nk:m@ >r
            "num" nk:m@ >r
            "a" nk:m@ r> r> w:exec
            "num" swap nk:m!
            "a" 0 nk:m!
          then
        ) nk:button-label rdrop
      ) a:each drop
    nk:layout-grid-end
  else
    drop
  then ;
  
: main-render
  {
    title: "calc",
    bg: "white",
    flags: [ @nk:WINDOW_NO_SCROLLBAR ],
    padding: [0,0] 
  } 

  nk:begin
    null { rows: [ @ROWHEIGHT, -1], cols: 1, rgap:4, cgap:4, margin: 4 } nk:layout-grid-begin
      0 1 0 1 nk:grid nk:rect>local nk:grid-push
        display
      1 1 0 1 nk:grid nk:rect>local nk:grid-push
        keys
      1 1 0 1 nk:grid
        2 2 "black" nk:stroke-rect
    nk:layout-grid-end
  nk:end ;

: app:main
  new-win ' main-render -1 nk:render-loop ;

Dsves IS written in Swift
Not SwiftUI though
So the UI definition is a bit different and not the declarative style SwiftUI uses
I think, & @DaveS can correct me, he still uses UIKit for iOS & AppKit for macOS

Have to still admit I find stack based … uh odd

32 constant FONTHEIGHT
1.2 FONTHEIGHT n:* constant ROWHEIGHT

is (I’m pretty sure)

CONST FONTHEIGHT = 32
CONST ROWHEIGHT = FONTHEIGHT * 1.2

Norman is correct, I do not use SwiftUI… so far all the articles I have read about it, don’t give me any incentive to change (yet)… as I too find the “stack based” design … odd

and if you are asking the Swift Syntax for this

let FONTHEIGHT : Double = 32
let  ROWHEIGHT = FONTHEIGHT * 1.2

you have to indicate data type for the first one, other wise it “guesses” INT
you don’t for the 2nd (although you should), because it knows FONTHEIGHT is already Double

That is correct conversion. Brain soon get’s used to it. I nowdays sometimes need a little time to adjust when I write in non stack based programming languages.

Do you layout UI in code or use a visual designer? I have seen some of your programs and like the visual appereance.

I have a visual designer that I created myself. I have a project to do the same for macOS, iOS and tvOS, but its one of those I work on for a few weeks, then let my brain cool off

The output from my designer is 100% code without the use of Autolayout constraints

I’ve only been at SwiftUI for a couple of weeks, so I’m not sure exactly how I would do it. Some of the ways how I would do things in the past, really don’t work well with SwiftUI.

I’m also short on time this weekend, I don’t know if I’ll be able to have a go myself, but I did some Googling and found this example. I can’t say if this is the best way or not, nor how I would do it, some aspects are as I imagined.

Just a reminder about this excellent iOS programming course, using Swift and SwiftUI. Free.

https://cs193p.sites.stanford.edu/2023

2 Likes

I had a bash today at replicating the macOS calculator in SwiftUI. Please remember that I’m still learning SwiftUI, so the code may not be the best way to do it. Most of it works, next I need to learn how to handle keyboard input (yes, that new to SwiftUI).

I actually wrote two versions, one using MVC, and one with the logic code in the UI, because with SwiftUI, do we need to separate it anymore?

2 Likes

8th uses Nuklear as it’s GUI. Nuklear is Immediate mode GUI, so separating logic and GUI is not possible. Some time ago I took a look at Qt based Felgo and it seemed to require only minimal amount of JavaScript for simple games.

1 Like

Hm, this looks like a nice compromise between a round-trip visual designer and a purely programmatic approach to building a GUI.

1 Like

Excellent course. thanks @prodman!
It provides context and insight into the (theoretical) underpinnings of Swift, valuable to non-pro coders who didn’t learn all that stuff from ground up.

I revisited Flutter and it is really something, and yes, from the Xojo background, generating UI in code is kind of awkward.

But, languaje is interesting, it really makes xojo look like outdated and limited. The instalation was not bad. and the best part was that it picked up my previous android SDK so offered to run as a windows app, web app and in an android device I had pluged in all from the exact same code base with no changes.

2 Likes

Can you share some example code and the result? Something like the calculator example. I’m interested to see how different it is to SwiftUI.

Calling @thorstenstueker and @Jeannot There must be some Declarative UI for Java, do you folk have any experience or recommendations?

JavaFX with FXML is a declarative approach for Java UI programming. But, while Java programmers are so lacy, on top there is a scenebuilder which you can use insteal of fxml. Fxml id over a decade there and works like a horse. That is the Java way. Long time before the rest wath considering it. The best: The Designer can use the Scenedesign Drag and Drop UI Designer and the programmer can work with the resulting fxml. Or use it like it is. Fast, working, neat. For Desktop, Web and mobile. But I have to warn: not native…only css driven and many things more.

2 Likes

I think UI designers are not a good fit anymore for responsive layouts of todays software. Also, for maximum control nothing beats doing things programmatically.

I personally mostly use grid layouts and for really exotic layouts, one can always use constraint solver.

2 Likes

To be fare Flutter is still not robust enough for building web apps.

And having built one web app I felt that it is very slow when it comes to user interaction on large 2k and 4k displays.

Another thing is that we need to use either Go or Rust based web server if we want good performance with larger number of user.

Using the default Flutter web server is very slow.

1 Like