Log in

View Full Version : Another task...



Tenian
August 29th, 2008, 00:27
I'm trying to create a window that has subwindows.
The left hand subwindow has a "drill down" style list:
Chapter->Section->Article
Really it is just a set of nested windowlists
I have that all working.

The right hand subwindow should have the text of the last article clicked on.

I can't figure out how to make this happen. If it's even possible. I thought in the onClickDown() of the article windowlist, I could set the database node of the right hand subwindow (thus populating it).

Possible? Or am I stuck just having the article window list throw up links that open separate windows.

Foen
August 29th, 2008, 06:10
I don't think you can set the database node of a sub-window: it always uses the same node as its parent window (thus all the tabs on a character sheet are just different views of the top-level database node).

That said, have you looked at the coding for the Library? It does something similar and maybe there's a trick or two you can learn from it.

An alternative approach would be to have a windowlist in the right pane, with only one item in it: you can set the window class and the database node for entries in a window list via the createWindowWithClass(class,dbnodeid) method.

Stuart

Tenian
August 29th, 2008, 13:38
That should work. I just never thought of doing it that way! Now I just have to wait for the end of the day to go home and try it :)

Tenian
August 29th, 2008, 23:10
I had nearly given up, fortunately your suggestion to use a windowlist and createWindow(), and pointing me to the library file were all I needed to get this working the way I imagined. (https://dnd-4e.blogspot.com/2008/08/foen-rocks.html)

https://4.bp.blogspot.com/_uDFpksWt8LQ/SLhzEvPrlMI/AAAAAAAAAvc/0521plGZ_ys/s1600-h/foen_rocks.jpg

Tenian
August 30th, 2008, 01:39
One of the advantages of building the modules the way I do is it's easy to extract all the keywords from say a formattedtext block and store them in a plain string field.

I built a filter that works on this string field...all works well except......

I have nested windowlists: chapter->section->article.
Right now if you punch words into the filter it expands any chapter->section->articles that match, perfect.
It also hides any articles that don't match (hence filter). What I'd like it to do is hide any chapter->sections that don't match as well.

I think this is possible. I have this block of code which sets the parents visible


if string.find(string.lower(w.keywords.getValue()), f, 0, true) then
top = w
while top.windowlist do
top.windowlist.setVisible(true);
top = top.windowlist.window;
end
return true;
end


I think what I need to do is something like this:



if string.find(string.lower(w.keywords.getValue()), f, 0, true) then
top = w
while top.windowlist do
top.windowlist.setVisible(true);
top = top.windowlist.window;
end
return true;
else
top = w
local needvis
needvis = false;

while top.windowlist do
for otherwindows in top.windowlist.getWindows() do
if otherwindows.isVisible() then
needvis = true
end
end
top.windowlist.setVisible(needvis);
top = top.windowlist.window;
end

end


This adds a branch for the case where the filter didn't match, it tries to check the other windows on the same level and if none of them are visible it will set the visibility of the level to off.

Unfortunately the for loop is throwing errors about an attempt to call a table value. I'm not surprised since I've never worked with one before :)

Foen
August 30th, 2008, 06:58
I'm not sure about your syntax for the 'for' loop, I usually use the following:


for i,win in ipairs(windowlist.getWindows()) do
...
end

or


for k,win in pairs(windowlist.getWindows()) do
...
end

The former approach iterates over the windows using an integer index, and the latter iterates over the windows using each window's node name.

I think you may also have a bit of trouble with your proposed code, as you are trying to set the visibility of higher-level windows from the onFilter event of the deepest child window. Unfortunately, not all the co-children will have been processed at any one time and hence you cannot guarantee that their visibility (as checked in the otherwindows for-loop) will have yet been set correctly.

A typical way to achieve what you are after would be to set the parent window visibility only after completing the bottom-level filter operation. It would also be more efficient as you only have to iterate over the entire hierarchy once. You could achieve this, I think, by adding code to the filter control rather than the windowlists.

Just a thought

Stuart

Tenian
August 30th, 2008, 11:21
I didn't want to do the processing at the deepest level but I was unable to find any documentation on filters. I have a filter and a filtertrigger element but the library doesn't contain either of these items (it goes from diefield to genericcontrol). So I used the time honored tradition of finding something that worked sorta like I wanted and began modifying it.


What events are available? Obviously I'd need something that triggers when the filter has completed processing. Or just a link to the documentation. One day I might understant the library (or they'll add a search feature...naw what kind of fool codes a search feature....wait).

Foen
August 30th, 2008, 11:39
I think the filter stuff is a template control, so the code sits in your ruleset already.

Cheers

Stuart

zabulus
August 30th, 2008, 13:46
I had nearly given up, fortunately your suggestion to use a windowlist and createWindow(), and pointing me to the library file were all I needed to get this working the way I imagined. (https://dnd-4e.blogspot.com/2008/08/foen-rocks.html)



LOL! Someone is happy he got this working :D

Bidmaron
August 30th, 2008, 14:06
Tenian, where can one find all your hard work? Is it all in 4eJPG? This sounds like it uses copyrighted material is why I ask. Does it all make it into 3.5eJPG?
--Dale--

Tenian
August 30th, 2008, 14:23
My work makes it into 4E_JPG.

The code behind what I do does not require use of any material protected under copyright. It is however designed to work with modules I create for my own personal use. I also publish the tools used to build those modules. This allows any individual to extract material from their legally owned copy of the PHB (or MM, DMG, adventure module, etc) and build a FG2 module custom designed to work with 4E_JPG, without knowing anything about XML, lua, or the underlying structure of 4E_JPG.

This particular item doesn't use any 4E specific objects, it's all (currently) contained in a reference_manual.xml file. It could be ported, with minimal effort to 3.5_JPG if moon_wizard was interested in doing so. The PHB parser which built this module could also be made to produce a 3.5 compatible module.

However, what you don't see is the 8-10 hrs I spent doing markup on the chapter I've been using as a sample. This is just adding a series of html tags, but it is a little tedious. The plus side is it doesn't require a lot of advanced skills to do.

Tenian
August 30th, 2008, 15:52
For some reason I find this problem extremely frustrating. I just don't think it should be so hard to hide a list if all of the windows under it are hidden.

There doesn't seem to be any sort of usable event to do what I want to do and looking at the template is of absolutely no help. I'm assuming I'd have to make a new LUA file for my filter but again I'm stuck on the fact I have no way to know when all the onFilter events have processed. Something like onListRearranged but fired at the end of the onFilter() event.

Foen
August 30th, 2008, 16:17
The filter is a template based on the string control, and as such you can add an onValuedChanged event handler of your own (provided you also remeber to call super.onValueChanged) which will respond at the top level of your hierarchy.

Please shout if you that doesn't help.

Stuart

Tenian
August 30th, 2008, 18:21
I'm missing something crucial.

This is how I want my code to look:


function onValueChanged()
super.onValueChanged();
local f = window.filter.getValue()
local showsection = false;
local showchapter = false;
for k, chapterwin in pairs(window.chapter.getWindows()) do
showchapter = false;
for k2, sectionwin in pairs(chapterwin.section.getWindows()) do
showsection = false;
for k3, articlewin in pairs(sectionwin.article.getWindows()) do
if string.find(string.lower(articlewin.keywords.getVa lue()), f, 0, true) then
showsection = true;
end
if showsection then
showchapter = true
end
end
sectionwin.setVisible(showsection);
end
chapterwin.setVisible(showchapter);
end
end


But it doesn't work.

The two set visible lines throw nil errors. Now I can change them to:


sectionwin.windowlist.setVisible(showsection);
chapterwin.windowlist.setVisible(showchapter);

but any value that activates the filter hides all the records.

It's probably blindingly obvious to everyone but me because I've been staring at it for so long. heh.

Foen
August 30th, 2008, 18:59
How about this:


function onValueChanged()
if super and super.onValueChanged then
super.onValueChanged();
end
local f = window.filter.getValue();
for k, chapterwin in pairs(window.chapter.getWindows()) do
local showchapter = false;
for k2, sectionwin in pairs(chapterwin.section.getWindows()) do
local showsection = false;
for k3, articlewin in pairs(sectionwin.article.getWindows()) do
if string.find(string.lower(articlewin.keywords.getVa lue()), f, 0, true) then
showsection = true;
end
end
if showsection then
showchapter = true
end
sectionwin.setVisible(showsection);
end
chapterwin.setVisible(showchapter);
end
end


Stuart

Tenian
August 30th, 2008, 19:10
nope...throws the exact same ni value setVisible error

Tenian
August 31st, 2008, 00:04
Okay...whatever the filter does is apparently not exposed...or if it is, I have no idea how to find it. But I did find a solution.

My structure is:
reference_manual has a windowlist of referencemanualchapter named chapter

referencemanualchapter has a windowlist of referencemanualsection named section

referencemanualsection has a windowlist of referencemanualarticle named article

On reference_manual there is a filter and filtertrigger that work on the article windowlist. This works like a charm.

Since filtering does what I want it to do for the lowest level list, I decided to apply it to all the other lists.

on referencemanualsection and referencemanualchapter I added the following to sheetdata:


<stringfield name="suppress">
<bounds>0,4,-1,15</bounds>
<static>0</static>
<invisible />
</stringfield>


I added the following to the referencemanualchapter section windowlist and the reference_manual chapter windowlist:


<script>
function onFilter(w)
if w.suppress.getValue() == "0" then
return true;
else
return false;
end
return true;
end
</script>


Finally I changed the reference_manual filter (this is the code from before) to be:



<script>
function onValueChanged()
if super and super.onValueChanged then
super.onValueChanged();
end
local f = window.filter.getValue();
for k, chapterwin in pairs(window.chapter.getWindows()) do
local showchapter = false;
for k2, sectionwin in pairs(chapterwin.section.getWindows()) do
local sectionx,sectiony = sectionwin.getSize()
local showsection = false;
for k3, articlewin in pairs(sectionwin.article.getWindows()) do
if string.find(string.lower(articlewin.keywords.getVa lue()), f, 0, true) then
showsection = true;
end
end
if showsection then
showchapter = true
sectionwin.suppress.setValue("0");
chapterwin.section.applyFilter()
else
sectionwin.suppress.setValue("1");
chapterwin.section.applyFilter()
end
end
if showchapter then
chapterwin.suppress.setValue("0");
window.chapter.applyFilter()
else
chapterwin.suppress.setValue("1");
window.chapter.applyFilter()
end
end
end
</script>


Now when the visible filter finishes, all the articles are checked to see if they passed the filter. It then sets all the section window's suppress fields and fires off the chapter.section windowlist's filter

Once it finishes the sections it moves up to the chapters. Depending on the sections visible, the chapter.suppress field is set. Then the window.chapter windowlist's filter is kicked off.

Foen
August 31st, 2008, 06:14
*slaps head*

I mislead you: there is no setVisible method for window classes, so using the filter technique is as good a method as any. I think you could call applyFilter less frequently (it only needs to be done once per list rather than once per list entry):


function onValueChanged()
if super and super.onValueChanged then
super.onValueChanged();
end
local f = window.filter.getValue();
for k, chapterwin in pairs(window.chapter.getWindows()) do
local showchapter = false;
for k2, sectionwin in pairs(chapterwin.section.getWindows()) do
local sectionx,sectiony = sectionwin.getSize()
local showsection = false;
for k3, articlewin in pairs(sectionwin.article.getWindows()) do
if string.find(string.lower(articlewin.keywords.getVa lue()), f, 0, true) then
showsection = true;
end
end
if showsection then
showchapter = true
sectionwin.suppress.setValue("0");
else
sectionwin.suppress.setValue("1");
end
end
chapterwin.section.applyFilter();
if showchapter then
chapterwin.suppress.setValue("0");
else
chapterwin.suppress.setValue("1");
end
end
window.chapter.applyFilter();
end

Also, I'm not sure why you are calling getSize() on sectionwin, I guess it is left over from an earlier approach?

Cheers

Stuart

Tenian
August 31st, 2008, 11:37
Yeah getSize was from an earlier attempt. Since I couldn't setVisibility, I tried to achieve the same thing by setting the size to 0,0 or back to whatever the size should be. I noticed it shortly after posting, when I was cleaning up the file.

You're right about the apply filter, they are really in the wrong loops, they should be one level higher.