Board index FlightGear Development Canvas

Creating a Widget of widgets  Topic is solved

Canvas is FlightGear's new fully scriptable 2D drawing system that will allow you to easily create new instruments, HUDs and even GUI dialogs and custom GUI widgets, without having to write C++ code and without having to rebuild FlightGear.

Creating a Widget of widgets

Postby Necolatis » Tue Nov 25, 2014 11:03 am

Hello,

I am creating a widget that is built of widgets. If I make a dialog window its fairly straightforward, as I can attach a box layout to the dialog, and just start adding widgets.
But when making a widget, I create a root group, which is seems to be a canvas group, where layouting is not enabled. How do I attach a layout? Or is there a better way to do this?

Here is a snippet of my faulty code:

Code: Select all
# A failure panel
DefaultStyle.widgets.failure = {
  new: func(parent, cfg)
  {
    me._root = parent.createChild("group", "failure");

    me._vbox = VBoxLayout.new();
    me._root.setLayout(me._vbox);  # this does not work of-cause
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby Hooray » Tue Nov 25, 2014 12:02 pm

I also ran into this a few months ago when I wanted to use layouts in combination with PUI/CanvasWidget:

Subject: Using a PUI CanvasWidget as a Canvas.Window ?
TheTom wrote:Image
Layouts don't require windows, you can apply a layout to any canvas. Window.setLayout just forwards it to Canvas.setLayout (although I forgot to expose this to Nasal -> me going to push^^)
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11427
Joined: Tue Mar 25, 2008 8:40 am

Re: Creating a Widget of widgets

Postby Necolatis » Tue Nov 25, 2014 1:00 pm

Thanks, adding it to canvas directly got me a bit further, it will now show.

Code: Select all
# A failure panel
DefaultStyle.widgets.failure = {
  new: func(parent, cfg)
  {
    me._root = parent.createChild("group", "failure");

    me._vbox = VBoxLayout.new();
    parent.getCanvas().setLayout(me._vbox);


But that only works because the canvas was already empty, had the widget been added to an existing layout it will replace the entire layout of that canvas and display itself all over that canvas instead of constraining itself inside the layout it is added to.

Not sure how to proceed with fixing that. Any suggestions?
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby Necolatis » Thu Nov 27, 2014 2:30 am

I prefer not to fill up DefaultStyle.nas with 1400 lines of extra code. But not sure how to make a widget that does not do that.
Hooray, could I perhaps be directed to the code for a widget you made?
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby TheTom » Thu Nov 27, 2014 10:26 am

You can use layouts inside custom widgets if you manually call setGeometry on the layout if the size of the widget has changed (eg. inside setSize of the widget). Have a look at the ScrollArea widget for an example.
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: Creating a Widget of widgets

Postby Necolatis » Thu Nov 27, 2014 2:26 pm

That seems to work. But as I could not find a way to get the layout it is put into, I added a 4th param:

Code: Select all
# A failure panel widget
gui.widgets.Failure = {
  new: func(parent, style, cfg, layout)
  {
    var m = gui.Widget.new(me);
    m._cfg = Config.new(cfg);
    m._focus_policy = m.NoFocus;
    m._setView( m._new(parent, style, cfg, layout) );

    return m;
  },

  _new: func(parent, style, cfg, layout)
  {

    me._root = parent.createChild("group", "failure");
    me._style = style;
    me._vbox = VBoxLayout.new();
    layout.addItem(me._vbox);
    ...


I call it like this:

Code: Select all
var FailureDialogW = {
  show: func
  {
    var m = {
      parents: [FailureDialogW],
      _dialog: canvas.Window.new([600,500], "dialog")
                         .set("title", "Failure Manager")
                         .set("resize", 1),
    };

    m._dialog.getCanvas(1)
          .set("background", canvas.style.getColor("bg_color"));
    m._root = m._dialog.getCanvas().createGroup();

    m._vbox = HBoxLayout.new();
    m._dialog.setLayout(m._vbox);
   
    io.include("Nasal/canvas/gui/widgets/Failure.nas");
    m._panel = gui.widgets.Failure.new(m._root, style, {}, m._vbox);
    m._panel2 = gui.widgets.Failure.new(m._root, style, {}, m._vbox);
  },
};

FailureDialogW.show();



Its seems to me real stupid to do it like this (but it works), any suggestion for doing it proper?
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets  

Postby TheTom » Thu Nov 27, 2014 4:35 pm

You should not let the compound widget add itself to the parent layout, but instead add the compound widget to the layout:

Code: Select all
m._vbox.gui.widgets.Failure.new(m._root, style, {});


Then, inside the Failure widget you have to call setGeometry on the layout if the size changes (inside setSize) and ensure the layout is parented to the widget. You can see this in the ScrollArea example.
I will update the update to make this easier by allowing to just set a layout for widgets.
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: Creating a Widget of widgets

Postby Necolatis » Fri Nov 28, 2014 6:50 am

Thanks, now I get it, got it to work now. :)
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby Necolatis » Fri Nov 28, 2014 7:50 am

Hold on, got another problem now:

Nasal runtime error: non-objects have no members
at d:\ProgramFiles\Development\Git\fgdata/Nasal/canvas/gui/Widget.nas, line 79
called from: d:\ProgramFiles\Development\Git\fgdata/Nasal/canvas/gui/Widget.nas, line 160

I am clueless in how to fix that.
This is the constructor:

Code: Select all
# A failure panel widget
gui.widgets.Failure = {
  new: func(parent, style, cfg)
  {
    var m = gui.Widget.new(me);

    m._vbox = VBoxLayout.new();
    append(m.parents, m._vbox);

    m._cfg = Config.new(cfg);
    m._focus_policy = m.NoFocus;
    m._setView( m._new(parent, style, cfg) );

    return m;
  },
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby Necolatis » Sat Nov 29, 2014 7:34 am

My widget is now being created more in style of the other widgets. It shows fine but I still get the above error, whenever it get focus.

This is how the widget looks:

Code: Select all
# A failure panel widget
gui.widgets.Failure = {
  new: func(parent, style, cfg)
  {
    var m = gui.Widget.new(gui.widgets.Failure);

    m._vbox = VBoxLayout.new();
    append(m.parents, m._vbox);

    m._cfg = Config.new(cfg);
    m._focus_policy = m.NoFocus;

    var w = {
      parents: [FailureFactory],
      _style: style,
      _vbox: m._vbox
    };
    call(FailureFactory.new, [parent, m._cfg], w);

    m._setView(w);

    return m;
  }
};

FailureFactory = {
  new: func(parent, cfg)
  {
   ...


I think Widget does a call to getCanvas() and get returned nil, but not sure why. Any help is appreciated.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby Necolatis » Sat Nov 29, 2014 11:12 am

..and won't there be a conflict, since both canvas.widget and layout has a getCanvas() function? Is that related to my problem?

The whole code is here: https://gitorious.org/fg/canvas-hackers ... ailure.nas
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby Necolatis » Sun Nov 30, 2014 11:32 am

After some investigation, I conclude that it is the buttons that fail when they get focus. A call in the button widget to getCanvas() returns nil. But I should be passing them a good _root (CanvasGroup), so I am clueless to how this can happen.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby Hooray » Sun Nov 30, 2014 11:35 am

is the root nil or is it some other/unexpected root, if it's the latter, the most common error that people tend to make is not wrapping arguments in a closure - have you checked that ?
If in doubt, I'd do a !=nil check in 3-4 places and use debug.dump() or debug.bt() if the root group is invalid.
I'll take another look at your code to see if I can spot anything obvious.

PS: Regarding your PM: no, I meant all those buttons in the randomPage() method that are lacking a var keyword (see here) - the reason for using the keyword are explained on the wiki: http://wiki.flightgear.org/Nasal_Variables#Variables
Also, it would be a good idea to post specific gitorious URLs here with line numbers for the errors you're getting (I cannot test/run anything ATM here)
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11427
Joined: Tue Mar 25, 2008 8:40 am

Re: Creating a Widget of widgets

Postby Necolatis » Sun Nov 30, 2014 5:18 pm

In line 78 of Widget.nas it says (and returns nil): https://gitorious.org/fg/canvas-hackers ... et.nas#L78

var canvas = me.getCanvas();

If I replace that with:

var canvas = me._view._root.getCanvas();

Then that works.

Somehow the getCanvas method fails inside the buttons, but that is inside C space I reckon. Maybe it has been overridden but I didn't do that. (directly anyway). I just use the button widgets normally, like this:

Code: Select all
    me._tab_failures = gui.widgets.Button.new(me._root, me._style, {})
                                    .setCheckable(1)
                                    .setChecked(1)
                                    .setFixedSize(75,25)
                                    .setText("Failures");
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2044
Joined: Mon Oct 29, 2012 12:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2019.1.2
OS: Windows 10

Re: Creating a Widget of widgets

Postby Hooray » Sun Nov 30, 2014 5:58 pm

Looking at the code, I'd consider moving the "tab" functionality to a dedicated/separate widget once this problem is solved - tabs seem like a useful thing in general, so I wouldn't add tab-specific code to the failure mgmt widget.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11427
Joined: Tue Mar 25, 2008 8:40 am

Next

Return to Canvas

Who is online

Users browsing this forum: YandexBot [Bot] and 2 guests