NiGui icon indicating copy to clipboard operation
NiGui copied to clipboard

Implemented GenUI for NiGui

Open PMunch opened this issue 6 years ago • 25 comments

This is an implementation of the GenUI macro for NiGui. It includes an example and an explanation of how to use it and what it is.

PMunch avatar Jul 11 '17 18:07 PMunch

Wow, very good work!

Yardanico avatar Jul 11 '17 19:07 Yardanico

But I think you need to make "genui" available when installing from nimble. Maybe move it under nigui directory?

Yardanico avatar Jul 11 '17 19:07 Yardanico

Sorry, my bad. It was made with the old folder structure, and I forgot to check when I merged in your changes to my fork. Should be fixed now.

PMunch avatar Jul 12 '17 08:07 PMunch

Is there a way to export variable from @result?

genui:
  Window[width = 800, height = 600, show]("Nickel"):
    LayoutContainer(Layout_Vertical):
      {var guiLog* = @result} TextArea()

this doesn't work. But I know that there's a workaround:

genui:
  Window[width = 800, height = 600, show]("Nickel"):
    LayoutContainer(Layout_Vertical):
      {var temp = @result} TextArea()
var guiLog* = temp

Yardanico avatar Jul 12 '17 10:07 Yardanico

Currently I need to use this as I need to export two variables:

genui:
  {var tempWin = @result} Window[width = 800, height = 600, show]("Nickel"):
    LayoutContainer(Layout_Vertical):
      {var temp = @result} TextArea()

var window* = tempWin
var guiLog* = temp

Yardanico avatar Jul 12 '17 10:07 Yardanico

Also I did a quick port of NiCalc gui to genui: I think @result can be shortcutted to "@" maybe? Because it takes many space

genui:
  {var window = @result} Window[width = 600, height = 450]("NiCalc"):
    LayoutContainer[padding = 6](Layout_Vertical):
      LayoutContainer(Layout_Horizontal):
        Label("Input:") [minWidth = labelWidth, heightMode = HeightMode_Fill]
        {var inputTextBox = @result} TextBox() [fontSize = editFontSize, fontFamily = editFontFamily]
        {var clearButton = @result} = Button("Clear") [minWidth = buttonWidth, heightMode = HeightMode_Fill]
      LayoutContainer(Layout_Horizontal):
        Label("Result:") [minWidth = labelWidth, heightMode = HeightMode_Fill]
        {var resultTextBox = @result} TextBox() [fontSize = editFontSize, fontFamily = editFontFamily]
      {var historyContainer = @result} LayoutContainer(Layout_Vertical)[frame = newFrame("History")]:
        {var historyTextArea = @result} TextArea() [fontSize = historyFontSize, fontFamily = editFontFamily]

But overall this looks much more clear than usual style (because you can immediatly see type of layout, and order of GUI elements)

Yardanico avatar Jul 12 '17 11:07 Yardanico

Ah yeah. The {} code thing is still a work in progress. Previous versions of genui used identifier % Button to assign a new button to the identifier "identifier". This was limited to only that though and couldn't be used for thing like array assignment and such. The plan with {} was to allow any code to be inserted but it proved a bit hard because of how Nim parses things before the macro gets a look at it. I'll try to work out something a bit more robust though. The @result was also a bit of a necesitty of the same reason, Nim refuses to parse only @. I was also thinking that maybe different @ values could be used to get different things, like using @children in a loop for a repeating section for example. But I agree that it's a bit long and clumsy.

PMunch avatar Jul 12 '17 16:07 PMunch

@PMunch anyway genui is a great addition to NiGui

Yardanico avatar Jul 12 '17 17:07 Yardanico

Oh thanks, I think so too. By the way, another workaround for your specific problem which might be better is to simply define the variable before assigning to it in the curly brackets like so:

var myButton*: Button
genui:
  Window[width=800, height=600]:
    {myButton = @result} Button("Hello world")

PMunch avatar Jul 12 '17 17:07 PMunch

Okay, I've now added a small check to the handling of pure code. If the only node in the code is a string literal it parses it as code instead of inserting it directly as code. This means that you can now do:

genui:
  Window[width=800, height=600]:
    {"var myButton* = @result"} Button("Hello world")

And that would be parsed into code and work as you would expect. It's not perfect but it should work for now.

PMunch avatar Jul 12 '17 18:07 PMunch

@PMunch thanks!

Yardanico avatar Jul 12 '17 18:07 Yardanico

Hmm, just talked to some guys over in the IRC channel and it seems like the error is with how curly brackets are parsed. I checked and if you simply add parenthesis like {(code)} then it also works fine (plus you get syntax highlighting).

PMunch avatar Jul 12 '17 18:07 PMunch

@PMunch thanks for this workaround! works perfectly

Yardanico avatar Jul 12 '17 18:07 Yardanico

How was the porting experience by the way? One thing I feel is important with genui is how it is a fairly simple conversion to actual code so you should be able to easily port examples over. I hate when working with Gtk and the GUI builder just to Google something and only finding code snippets which I can't easily convert, or vice versa.

PMunch avatar Jul 12 '17 18:07 PMunch

@PMunch porting NiCalc gui to genui was fairly simple.

genui is the best for projects where GUI code is larger than one screen in length. For example NiCalc has 47 lines of gui creating code (including some spaces between different sections)

And also for now nigui doesn't contain many widgets, but I think this will improve in the future. Maybe this is the GUI framework for Nim that we've waited for :)

Yardanico avatar Jul 12 '17 18:07 Yardanico

I'm definitely hoping so, which is why I wanted to port genui to it as quickly as possible. I added a shorthand @r now by the way that can be used instead of @result, is that a fair compromise?

PMunch avatar Jul 12 '17 18:07 PMunch

@PMunch yeah, thanks again!

Yardanico avatar Jul 12 '17 18:07 Yardanico

So, let's wait for @trustable-code :)

Yardanico avatar Jul 12 '17 19:07 Yardanico

Great work :+1:

oskca avatar Dec 16 '17 01:12 oskca

@trustable-code so what is the status of this PR?

Yardanico avatar May 07 '18 19:05 Yardanico

@Yardanico I don't like additional complexity and don't see an advantage of using such macros as of now.

simonkrauter avatar May 07 '18 19:05 simonkrauter

I wrote a bit about the benefits of this system in my post here(primarily under the "A simple GUI DSL" heading). The macro in play here is actually fairly simple as long as the general interface is kept fairly uniform. It maps 1:1 from the DSL input to generated code, and doesn't really do a whole lot more than structure the code. The entire implementation is only about 150 lines, and could probably be shortened even more, plus it would probably not have to be changed at all for the foreseeable future unless you add some widgets which acts completely different than the ones you've got.

PMunch avatar May 07 '18 21:05 PMunch

Well technically yes. The wxNim version of genui was made a part of wxNim simply because I had to make changes to the code in order to make it work for all widgets. For NiGui on the other hand it could easily be implemented as an entirely different package. Although there are benefits to keeping it as a single thing. First of people making changes to NiGui would have to be aware of it, second it would make testing a whole lot easier.

PMunch avatar Jul 01 '18 19:07 PMunch

I tried to add "genui:" & add the various ui elements for nigui's example_02_controls.nim but hit: Error: undeclared identifier: 'genui'

andrewgohlk avatar Jun 19 '21 08:06 andrewgohlk

@andrewgohlk, on my fork, or the main repository? This PR is pretty outdated by now, no idea if it still works or not.

PMunch avatar Jun 29 '21 11:06 PMunch