Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

controlgallery.nim fails with "object.nim(37, 78) Error: invalid indentation" #28

Open
harrier77 opened this issue Feb 14, 2024 · 20 comments

Comments

@harrier77
Copy link

I have followed the instructions in Readme: cd examples/genuimacro nim cpp -r controlgallery.nim but the compiler exits with this wxnim-master/wxnim/private/object.nim(37, 78) Error: invalid indentation

I tried to edit the code, re-enter the indentation as tab (not allowed) and as spaces (2 or 3), nothing works. I think I am missing something about nim syntax.

@PMunch
Copy link
Owner

PMunch commented Feb 14, 2024

I haven't had time to test this, but looking at that line I believe it is the pragma syntax which has gotten stricter. If you move the [T] part to right after the * I believe it should work. Granted this project hasn't been touched in quite a while, so you might run into other issues..

@harrier77
Copy link
Author

harrier77 commented Feb 14, 2024

This is the line:
37 WxObjectDataPtr* {.importcpp: "wxObjectDataPtr", header: wxh, inheritable.}[T] = object
What do you mean with "move the [T] part to right after the *"?
The [T] is already on the right part just before the =.

But I tried with WxObjectDataPtr*[T] and actually the compilation goes on, it stops after some other lines:
object.nim(65, 42) Error: undeclared identifier: 'WxClassInfo' . Maybe the line 37 error is resolved but there is something else.

@PMunch
Copy link
Owner

PMunch commented Feb 14, 2024

Yes, that's what I meant by right after the *. Are you still trying to compile the controlgallary? Or did you now try to compile just object.nim? It can't be compiled on its own because it relies on being include-ed at the right place.

@harrier77
Copy link
Author

I tried to compile controlgallary and it stops at line 65 of object.nim with "Error: undeclared identifier: 'WxClassInfo'"
If I try to compile object.nim by itself, it stops at line 15 object.nim(15, 42) Error: undeclared identifier: 'wxh'
It seems to have no sense, it passes line 15 when is linked to controlgallery but has error by itself.

@PMunch
Copy link
Owner

PMunch commented Feb 14, 2024

It actually makes perfect sense. In Nim import and include are two different things. The former is a nice hygienic thing which does namespaces and deduplication and all that jazz, while the latter is a simple copy-paste of the file into your current source file. That's why object.nim won't compile on its own and fails in a different place. The error in this case was caused by the {.noforward: on.} pragma in wx.nim changing name to {.experimental: "codeReordering".}. There was a hint about this in the compilation output.

After having fixed that and a couple more misplaced generics in the code I managed to get further in compiling. However I hit a dead end at the "implicitDeref" experimental pragma which was removed in Nim 2.0.0. This is unfortunate as it requires a rewrite of this library to be functional again. However I have pushed my changes as they are backwards compatible with 1.6.18, which still compiles this just fine (and is still supported).

@harrier77
Copy link
Author

Ok, I misunderstood your previous post. Yes, it has perfect sense, the object works only when included. Thanks for your work on this Library if you succeed in making it work again I can help you in some way testing it. I want to learn nim coding a small interface with WebView and wxwidget.

@PMunch
Copy link
Owner

PMunch commented Feb 14, 2024

I mean you can just run choosenim 1.6.18 and the library still works if you want to use it. But I'll try to get this fixed up at some point.

@harrier77
Copy link
Author

Ok, it works. Thank you for suggesting the use of choosenim, now I have two version of nim installed and I can switch very easy from one to the other. (I have to understand where both are installed )

@harrier77
Copy link
Author

harrier77 commented Feb 15, 2024

I tried the examples, with genui and without.
But it's not easy for me to manage the various options only using the source code of wxnim as reference. Are there examples with different combinations of controls and layout?
With c++ I use wxlglade to set up the position of controls and sizers and so on.
And after exporting the code I can learn the syntax.
For example I have this cpp code,
panel_1 = new wxPanel(this, wxID_ANY);
wxGridSizer* grid_sizer_1 = new wxGridSizer(3, 3, 0, 0);
grid_sizer_1->Add(0,` 0, 0, 0, 0);
grid_sizer_1->Add(0, 0, 0, 0, 0);
grid_sizer_1->Add(0, 0, 0, 0, 0);
grid_sizer_1->Add(0, 0, 0, 0, 0);
button_1 = new wxButton(panel_1, wxID_ANY, wxT("Avvia"));
grid_sizer_1->Add(button_1, 0, wxALIGN_CENTER, 0);
grid_sizer_1->Add(0, 0, 0, 0, 0);
grid_sizer_1->Add(0, 0, 0, 0, 0);
grid_sizer_1->Add(0, 0, 0, 0, 0);
grid_sizer_1->Add(0, 0, 0, 0, 0);
panel_1->SetSizer(grid_sizer_1);
Layout();

How can I rewrite it using genui or purewx?

@PMunch
Copy link
Owner

PMunch commented Feb 16, 2024

For purewx it should be pretty much the same, just convert the syntax to Nim. For genui I believe something like this would be what you're looking for:

# NOTE: these imports are relative to this folder, this would not be required if wxnim was installed with Nimble
import "../../wxnim/wx", "../../wxnim/genui"

# Experimental is required for now, this will become default later
{.experimental: "implicitDeref".}

# Generate the GUI
genui:
  mainFrame % Frame(title = "Hello World"):
    Panel | Gridsizer(3, 3, 0, 0):
      Button[flag = wxAlignCenter]: "Avvia"

# Show the main frame and run the main loop
mainFrame.show()
runMainLoop()

As you can see you use the | operator to attach a sizer to an element, and [] to set the arguments when adding to a sizer. Adding elements to other elements and sizers are done automatically by indentation.

@PMunch
Copy link
Owner

PMunch commented Feb 16, 2024

By the way, you can pass --expandMacro:genui during compilation and Nim will show you what the genui macro expands to which is very helpful.

@harrier77
Copy link
Author

Thank you, I can watch the macro expanded.
Now I can place Button in cell at position 0,0 of the grid, but in the code generated by wxglade I was able to place it in the position 1,2 using "grid_sizer_1->Add(0, 0, 0, 0, 0)" 3 times in the first row and 1 time in the second, (the same way I should use "td /td" in html).
How can I do the same using genui?

@harrier77
Copy link
Author

By the way, I have just installed wxformbuilder, it seems better that wglade and it can export python, cpp and lua.
How difficult is to create a plugin to make it export in nimx genui macro?

@PMunch
Copy link
Owner

PMunch commented Feb 16, 2024

You can just do the same thing in WxNim:

# NOTE: these imports are relative to this folder, this would not be required if wxnim was installed with Nimble
import "../../wxnim/wx", "../../wxnim/genui"

# Experimental is required for now, this will become default later
{.experimental: "implicitDeref".}

# Generate the GUI
genui:
  mainFrame % Frame(title = "Hello World"):
    panel % Panel | Gridsizer(3, 3, 0, 0)

panel.getSizer.add(0, 0, 0, 0)
panel.getSizer.add(0, 0, 0, 0)
panel.getSizer.add(0, 0, 0, 0)
panel.getSizer.add(0, 0, 0, 0)

panel.addElements:
  Button[flag = wxAlignCenter]: "Button"

# Show the main frame and run the main loop
mainFrame.show()
runMainLoop()

Of course you could've just added some StaticText: "" elements in the original definition to fill those cells as well.

As for wxformbuilder/wxglade I have no idea, never used either of them.

@harrier77
Copy link
Author

Thanks!
It works exactly as intended. But now I have to understand better the syntax: the four times panel.getSizer.add(0, 0, 0, 0) are not indented, so for what I can understand it means that they are outside genui macro, or am I wrong? And why is there a % before "Panel"?

@PMunch
Copy link
Owner

PMunch commented Feb 16, 2024

Did you read the explanation of the genui macro in the README? https://github.com/PMunch/wxnim?tab=readme-ov-file#the-genui-macro

Basically the genui macro here is run, and creates a frame and a panel with a sizer. The frame is assigned to the variable mainFrame and the panel is assigned to the variable panel (this is what the % symbol does.

Then outside the genui macro we use the panel variable that was just created for us to run normal wxWidget code on the panel, in this case we get the sizer and add some empty spacers to it. Then we call the addElements macro which is essentially the exact same thing as the genui macro, but it adds elements as the child of an existing element, just as if it was indented under it in the original genui call.

@harrier77
Copy link
Author

Thank you very much. I started to read the explanation in Readme and now I can understand almost everything. If I need some other hint I will contact you. But it seems that the Readme is enough for what I have intention to do.

@PMunch
Copy link
Owner

PMunch commented Feb 16, 2024

Great to hear, if you make it open source I'd be very interested to see what you make with this!

@harrier77
Copy link
Author

Probably you overrate my skills. The app I coded at now is a small panel with three buttons. I need it to launch chrome to browse a local httpd in nim which serves html pages dynamicaly generated with the list of directories full of documents.
My next step is to replace chrome with a WebView in a window coded in wxnim.

But you may be interested to know that the panel with three buttons in wxnim needs 36 rows of code, in cpp 138. Your macros are very powerful.

@harrier77
Copy link
Author

Here I am again. I tried very hard to got webview functioning, as an exercise to improve my understanding of the whole nim and c. In short:

  • I can use webview in python with this: self.browser = wx.html2.WebView.New(self)
  • I can use webview in C++ with this: myWeb = wxWebView::New( this, wxID_ANY, wxWebViewDefaultURLStr );
  • I tried in many ways in nim "let wv = cnew constructwxWebView(result,wxID_ANY,"http://localhost:8080")" without success...
    What is wrong?
    PS: the result I pass to cnew constructwxWebView is got by cnew constructWxFrame

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants