PDA

View Full Version : Help with Subwindows



Foen
November 30th, 2007, 11:59
I am trying to access the parent window of a subwindow from Lua script. According to the documentation:


A reference to the subwindow object is available from the script environment of the contained window instance through the variable subwindow.

However, I get the error message attempt to index global 'subwindow' (a nil value) whenever I try :confused:

The context is as follows:



<windowclass name='subclass'>
<script>
local node = subwindow.getDatabaseNode();
<script>
</windowclass>

<windowclass name='main'>
<sheetdata>
<subwindow name='subwindow1'>
<class>subclass</class>
</subwindow>
</sheetdata>
</windowclass>


Any clues?

Stuart

Hamish
November 30th, 2007, 12:16
Just had a quick search through the d20 scripts and I think the subwindow variable is actually an array of all subwindows, so you need to use an index or name when using it i.e. subwindow[1] or subwindow[name].
The files template_filter.lua and template_tabcontrol.lua use the subwindow variable on lines 57 and 24+43 respectively.

P.S. I have learned a lot from using the Shift-Ctrl-F combination in Notepad++ :D

Foen
November 30th, 2007, 13:49
Thanks Hamish, but I think that is an unfortunate coincidence. The subwindow array is actually created by the tabcontrol from its xml elements (you can access an xml element direct from script using the element notation, which is quite handy).

Digging further, I have found that the subwindow property provides a reference to its contained window from the subwindow element. The following snippet retrieves a reference to an instance of subclass:



<windowclass name='subclass'>
</windowclass>

<windowclass name='main'>
<script>
local win = subwindow1.subwindow;
</script>
<sheetdata>
<subwindow name='subwindow1'>
<class>subclass</class>
</subwindow>
</sheetdata>
</windowclass>


So the documentation should say:


A reference to the [i]contained window instance is available from the script environment of the subwindow object through the variable subwindow.

There doesn't seem to be an easy way to refer 'upwards' in the hierarchy from a contained windowinstance. I have instead used the Interface.findWindow() function as a work-around:



<windowclass name='subclass'>
<script>
local parent;
function onInit()
parent = Interface.findWindow("main",getDatabaseNode().getNodeName());
end
</script>
</windowclass>

<windowclass name='main'>
<sheetdata>
<subwindow name='subwindow1'>
<class>subclass</class>
</subwindow>
</sheetdata>
</windowclass>


Cheers

Stuart

Hamish
November 30th, 2007, 14:20
Long live the Hungarian notation (https://en.wikipedia.org/wiki/Hungarian_notation). :square:
So these are two variables with the same name. Well, of course technically speaking they're not variables at all, but I won't go into that. And I thought working with the "chat" window of the "chat" window class was confusing. :hurt:

I think I remember reading something in the documentation about a 'super' object referring to a control's parent window. Maybe it works for getting to the parent of a subwindow as well.

I am getting curious about what you're trying to do, BTW.

Foen
November 30th, 2007, 15:15
The super property enables a derived class to access base class properties and functions, so it applies to an inheritance hierarchy rather than a containment one, sadly. As an aside, the self property can be used in the base class, to access over-ridden/derived class properties and functions. I also use it when I have local variables with the same name as a window control:



function setName(name)
self.name.setValue(name);
end


The project I'm working on has a skills sheet and an abilities sheet, and I'm trying to access window controls in one from window controls in the other. I cannot use the underlying database nodes, because some of the controls are unbound :(

I think I'm just about there though!

Thanks for your help and encouragement: the more I do this stuff, the more ignorant I realise I am.

Cheers

Stuart

Dachannien
November 30th, 2007, 17:25
You could make this work - possibly - by registering the parent object with the child object during the parent's onInit().

Foen
November 30th, 2007, 18:03
I could, it's probably the most straightforward answer (and hence the most appealing). It would be nice to have an exposed property, nonetheless.

Stuart

Foen
November 30th, 2007, 19:10
The plot thickens...

The subwindows don't initialise before the containing window (unlike other windowcontrols), but rather when they are first shown, it seems.

The parent cannot therefore register itself during onInit, as there are no subwindows to register with :(

Back to my original method, I think.

Stuart

joshuha
November 30th, 2007, 20:37
The plot thickens...

The subwindows don't initialise before the containing window (unlike other windowcontrols), but rather when they are first shown, it seems.

The parent cannot therefore register itself during onInit, as there are no subwindows to register with :(

Back to my original method, I think.

Stuart

Yeah I found this out when doing the Savage Worlds ruleset. I have a calculated field on the first main window that wanted to access a field control on the skills tab but it doesn't create the field until that subwindow was opened.

One way I was thinking of getting around it was to just declare every single field on the main subwindow and just have the other subwindows call their own instance of that control. But in my case they are all DB bound nodes so that works. Wouldn't work for unbound controls.

Foen
November 30th, 2007, 22:14
Luckily for me, the calling subwindow is displayed after the called subwindow (abilities show first on the character sheet, you then have to click onto the skills sheet), otherwise this would be a real headache.

Stuart

Toadwart
December 1st, 2007, 04:00
Hiya Foen, I'm just about to go into a game session so haven't read through all the posts above.
However, I think the onInstanceCreated event might be worth investigating.
I recall having trouble with onInit and subwindows and this event helped me immensely...

Foen
December 1st, 2007, 08:27
Good steer Toadwart!

For the sake of those who follow, I'll set out what I have learnt. The context is:



<windowclass name='charsheet'>
<subwindow name='skills'>
<class>skillwindow</class>
</subwindow>
</windowclass>

<windowclass name='skillwindow'>
</windowclass>


The sequence of events is:
- onInit fires for the subwindow object (skills)
- onInit fires for the main window (charsheet)
- the user clicks the skills tab
- onInit fires for the contained window instance (skillwindow)
- onIntanceCreated fires for the subwindow object (skills)

To register the outermost window (charsheet) with the innermost one (skillwindow), the code is placed in a script block for the subwindow object (skills) to respond to the onInstanceCreated event:



<windowclass name='charsheet'>
<subwindow name='skills'>
<class>skillwindow</class>
<script>
function onInstanceCreated()
subwindow.registerParent(window);
end
</script>
</subwindow>
</windowclass>

<windowclass name='skillwindow'>
<script>
local parent = nil;

function registerParent(win)
parent = win;
end
</script>
</windowclass>


Note that the parent local variable is only set after the inner window has initialised, so 'parent' isn't available to skillwindow.onInit().

Cheers

Stuart