PDA

View Full Version : window setSize() not behaving with filtered list



phantomwhale
December 23rd, 2012, 21:26
I've been having issues with the Savage Worlds mini-sheet, and the ammo trackers on it. This mini-sheet is set to only display ammo trackers for weapons with max ammo greater than 0, and type of non-melee. It does this via a filter.

Because this means the window needs to change size when the list grows, I have written a script to call window.setSize() to the appropriate size, which works when the window is opened, but after that does not appear to work at all (the workaround being to close and reopen the window).

I tired to narrow down the issue by creating a test windowclass called "size test", which I include below - paste this into base.xml and you can invoke it by typing the following into the chat window


openwindow sizetest

What happens now if you can create extra string elements in the list using the radial menu. Once each column is full, it correctly resizes the window up. Equally, once an item is deleted via the radial menu, it correctly resizes the window down.

The problem comes when you change one of the string elements inside a window object to "off". This then causes it to filter. It does filter correctly, and dynamically resizes the windowlist correctly too, but somehow the call to resize the window down fails. The odd part is you can see the resize calls in the chat log, and these seem to claim the window HAS been resized (e.g. it calls window.getSize() and shows the size has gone down) !

In the case of the ammo tracker in the mini-sheet, you can manipulte the weapons to "unfilter" too by adjusting them on the main character sheet. Likewise this also fails - the list dynamically grows, calls window.setSize() on the minitracker window, but the window doesn't resize (despite saying it has) and the ammo tracker list is chopped off.

I dare say the test list would work this way too, but I haven't written a clever way to unfilter a window to prove it.

This is probably a query for moon_wizard, as I suspect it involves the underlying code, but if anyone has had a similar problem with filtered windowlists and window.setSize() I'd be interested to see how you got around it (or how it's working fine at your end !)

Cheers,
-PW-

The test code is as follows


<windowclass name="basicstring">
<sizelimits>
<minimum>
<height>20</height>
<width>125</width>
</minimum>
<maximum>
<height>20</height>
<width>125</width>
</maximum>
</sizelimits>
<sheetdata>
<stringfield name="name">
<bounds>5,0,120,20</bounds>
<empty>on</empty>
</stringfield>
</sheetdata>
</windowclass>

<windowclass name="sizetest">
<sizelimits>
<minimum>
<width>300</width>
<height>49</height>
</minimum>
</sizelimits>
<nopositionsave />
<frame>sheetgroup</frame>
<sheetdata>
<windowlist name="testlist">
<anchored>
<left>
<anchor>left</anchor>
<offset>18</offset>
</left>
<right>
<anchor>right</anchor>
<offset>-18</offset>
</right>
<top>
<offset>16</offset>
</top>
</anchored>
<frame>
<name>sheetgroup</name>
<offset>13,13,13,18</offset>
</frame>
<datasource>.strings</datasource>
<class>basicstring</class>
<columns>
<width>125</width>
<fillwidth />
</columns>
<createonempty />
<allowcreate />
<allowdelete />
<script>
function onFilter(w)
if w.name.getValue() == "off" then
return false;
end
return true;
end

function onListRearranged()
local ww, wh = window.getSize();
local n = 0;
for k,v in ipairs(getWindows()) do
if onFilter(v) then
n = n+1;
end
end

wh = 35 + math.ceil(n/2) * 20;
Debug.chat("Window size changing from", window.getSize())
window.setSize(ww, wh);
Debug.chat("Window size changed to", window.getSize())
end
</script>
</windowlist>
<close/>
</sheetdata>
</windowclass>

Moon Wizard
December 26th, 2012, 22:14
The challenge is definitely in the layout engine for the FG client.

Basically, here is what happens mostly:
* Changes in the data cause filter to be applied
* The filter flag is set for the windowlist, and the layout flag is set for the window
* On the next draw cycle, the window layout begins with the original size value.
* The layout triggers the filters
* The filters trigger the list rearranged event
* The list rearranged event calls setSize (which works internally)
* The setSize calls another nested layout which sets the window and list control size.
* The window layout completes, but overwrites the size value with the original size value.

All in all, you should avoid placing resize functions in the onFilter and onListRearranged event functions. Instead, trigger the change on an onValueChanged event.

Regards,
JPG

phantomwhale
December 26th, 2012, 23:49
Thanks for explaining the guts - trial and error is painful for these parts :)

A very inefficient and hacky adjustment to the windowlist got everything up and running (this was after I moved all the resizing code into an update() method on the main window itself, and then had onListRearranged() calling window.update() before)



function onInit()
getDatabaseNode().onChildUpdate = window.update
end


WIll probably tighten this up a little later on, but it seems to be performing OK right now.