PDA

View Full Version : Something I'm trying to do....



Tenian
July 16th, 2008, 15:19
This is all within a module.

In module 1 the library displays: Equipment - Weapons. This is an item I've created in the <library> block.

This opens a window that displays the names of all the weapons (Club, Dagger, etc). Each of these has the gray box that can be used to drag/drop or to open the weapon and display more detail (weight, damage, cost, etc). These can also be dropped onto character sheets.

In module 2 (made by someone else). I have the same data, but it is displayed in tabular form. Clicking on the link from the library pulls up a wide text window and displays a formattedtext string. It's all just one giant table. It doesn't link to anything, but it's much nicer for quick reference.

What I want to do is merge the two. I would like the data displayed in a somewhat tabular format and each row of that table contain the gray box link. I'm not sure if it's possible to actually build a table and have the link in one of the fields.
Alternatively if I could build a list that displayed the link and a field of formattedtext then I could achieve a similar effect.

I've worked with lists that are a link and a string. But I can't find any that are a link and formattedtext. Any pointers?

See below for my crude examples the [ ] represents a click/drag/drop link



Module 1
Weapons
[ ] Club
[ ] Dagger
....
Module 2
Weapons
Club 1d4 1 lb 1 gp
Dagger 1d6 1 lb 2 gp
.....

I want:
Weapons
[ ] Club 1d4 1 lb 1 gp
[ ] Dagger 1d6 1 lb 2 gp
......

Foen
July 16th, 2008, 16:46
I think you can do this two ways: custom windowlists; or formatted text tables. The former is neater.

Custom Windowlists

Note: This cannot be achieved only using modules (you have to edit the ruleset) but the data can be saved in a module.

You will need to create a new windowclass to hold the weapon table (say, indexweapons) which has the table column heading and a windowlist control with an entry for each weapon. The windowlist needs to use a second custom windowclass (say, indexweaponentry), which has string and number fields for each of the columns, and a windowopenfield for your grey drag-able box.

This can be laid out very neatly, but it can be an exercise in patience trying to get the column headings lined up with the fields! As the rows are rendered using a windowlist control, you can even add script to shade alternate rows, making the table much easier to read.

Formatted Text Tables

Most module builders use the html-lite features of formatted text to render tables, using table/tr/td tags. The advantage of this method is that no customisation is needed in the underlying ruleset, and no coding is needed (so the task can be accomplished by more folks).

To embed a link tag in the formatted text, nest it within a td tag and it works fine. Unfortunately, you have little control over how the table renders (row heights etc) and it doesn't mix well with long field contents which wrap, so the result isn't as attractive.

You cannot have row shading using this method, as there is no control over shading or background in the formatted text html.

I hope that helps,

Stuart

Tenian
July 16th, 2008, 18:01
Method two doesn't appear to be working.
Inside my table I added a <td><listlink type="windowreference">....</listlink></td>

Instead of the link I get the text between the listlink with the tags removed

i.e.
<listlink
type="windowreference"><class>referenceweapon</class><recordname>reference.weapon.club@4E Test</recordname</listlink>

displays as

referenceweapon reference.weapon.club@4E Test

Foen
July 16th, 2008, 18:29
I think you have to put the list tags around the listlink. It is a list of only one item.

Stuart

Tenian
July 17th, 2008, 03:55
Alright I got it working. And since I love to torture myself...how would I go about doing the alternating shading you mentioned?

You can see the results of my efforts on my blog (https://dnd-4e.blogspot.com/2008/07/its-like15-years-ago.html)

Foen
July 17th, 2008, 06:06
That only works using the first method, and it uses a frame to colour the background of the items in the windowlist, you should be able to use something like rowshade from the default d20 ruleset.

Add a handler in the windowlist script block for the event onListRearranged, which does something along the lines of:



function onListRearranged()
local alt = true;
for i,win in ipairs(getWindows())
if alt then
win.setFrame(myshade,0,0,0,0);
else
win.setFrame(nil);
end
alt = not alt;
end
end


I can't be sure if this is exactly right, especially the syntax for setFrame, but you get the idea.

Stuart

Tenian
July 18th, 2008, 02:04
Just a few minor things:

The decimal values in my table get displayed with many digits (0.20000000 instead of 0.2 for example). Are there formatting options for number fields that control the decimal places?

Is it possible to supress a field if the value is 0. Instead of displaying 0 I'd like to display a blank.

A picture is worth 1000 words. (https://dnd-4e.blogspot.com/2008/07/phb-009810.html)

Foen
July 18th, 2008, 06:20
I've never seen many decimal places before, nor do I know of any formatting options for numberfields (BTW that is something which is dearly missed).

On the blanks versus zeroes, you can use the tag <hideonvalue>0</hideonvalue> in the control definition.

Cheers

Stuart

Tenian
July 18th, 2008, 10:00
Is it possible to convert the number value to a string and then trim it to a fixed length?

Oberoten
July 18th, 2008, 20:55
Get the value, round it with a script call to this..





function RoundedTo(var, dec)
return math.floor( ( (var) * 10^dec) + 0.5) / (10^dec);
end

Foen
July 18th, 2008, 21:05
There is no problem taking a number and re-formatting it at a string (and hence controlling the number of decimal places) but that is only useful in a write-only (static) situation. it would be nice to have editable, formatted number fields available.

Back to your question in point. The Lua method string.format() provides the basic functionality you need, but it follows C-style (printf) formatting rather than VB-style formatting. I'll not enter into a debate on which is better, just suffice it to say they are different.

The string.format() method is documented (loosely) in the Lua Reference Manual, and the printf function is in any C, C++ or C# reference you can find.

I think for one decimal place (say) you would use string.format("%04.2f",num) to turn num into a string. As you are no longer using numbers, hideonvalue won't work, so you need to do something like:


if num==0 then
str = "";
else
str = string.format("04.2f",num);
end


Hope that helps

Stuart

Foen
July 18th, 2008, 21:07
Of course Obe's answer also works (sticks tongue out at Oberoten), but if you are plagued with spurious extra decimal digits, it may not suppress them. OK, it probably will.

Stuart

Tenian
July 18th, 2008, 22:12
But I went another way. The code that produced the extra decimals looked like this:


<script>
function onInit()
weapontablenode = link.getTargetDatabaseNode();

if weapontablenode then
local holdnode = weapontablenode.getChild("name");
if holdnode then
name.setValue(holdnode.getValue());
end
............
holdnode = weapontablenode.getChild("cost");
if holdnode then
cost.setValue(holdnode.getValue());
end
..........


I decided to change the module so the values were all on the same level. This allowed me to get rid of the script block (and seems to have made it run faster). As a bonus it fixed the spurious decimals.

Tenian
July 19th, 2008, 06:02
Having the table window open seems to consume a lot of CPU. Any idea why? It only has a handful of script elements in it and removing them didn't make any notable difference in CPU usage.

Foen
July 19th, 2008, 07:52
I think this has been discussed on another thread (https://www.fantasygrounds.com/forums/showthread.php?t=2467) but it isn't supposed to be a problem.

I'd guess it is tied in to the DirectX framework, but I'm shooting in the dark (not my area of expertise).

Stuart

Tenian
July 19th, 2008, 20:43
Well it doesn't completely floor my CPU. It just spikes it up 10-20% over most of the other lists. Of course most of my other lists are just a link and a name.

I guess since my tables are more complex (i.e. many more string,number fields). It makes sense they use a little more CPU. I was just trying to make sure I wasn't doing something that was causing the issue.

Tenian
July 23rd, 2008, 17:20
Is there a way to set the alignment for a stringfield? I've tried various tags <left />, <right /> , <center /> etc and they appear to have no effect. I didn't see anything in the help either.

Foen
July 23rd, 2008, 18:07
The documentation for textbasecontrol (https://www.fantasygrounds.com/refdoc/textbasecontrol.xcp) from which stringfield inherits, has a <center/> tag.

For right-alignment, I tend to anchor the field on its right, specify a vertical anchoring and a height, and then the control re-sizes leftwards. It gives some of the same effect.

Stuart

Tenian
November 11th, 2008, 18:02
So it seems like forever, but I was in a table and decided to try to add alternating row shading.

It works..sort of...it doesn't play nice with the filter and I can't see why:

I have a windowclass reference_featgrouplistitem
It has a windowlist featlist
featlist has a script block with 2 functions (onInit and onFilter):

function onInit()
local alt = true;
for i,win in ipairs(getWindows()) do
if alt then
win.setFrame("rowshade",0,0,0,0);
else
win.setFrame(nil)
end
alt = not alt;
end
end;



Now I know it should be in onListRearranged or a similar function, but this was for testing.

Now here's the rub, there's another function in the script block:


function onFilter(w)
local top = w.windowlist.window;
while top.windowlist do
top = top.windowlist.window;
end
local f = string.lower(top.filter.getValue());

if f == "" then
w.windowlist.window.description.setVisible(true);
w.windowlist.window.spacer.setVisible(true);
w.windowlist.window.labname.setVisible(true);
w.windowlist.window.labprerequisite.setVisible(tru e);
w.windowlist.window.labshortdescription.setVisible (true);
return true;
end

w.windowlist.window.description.setVisible(false);
w.windowlist.window.spacer.setVisible(false);
w.windowlist.window.labname.setVisible(false);
w.windowlist.window.labprerequisite.setVisible(fal se);
w.windowlist.window.labshortdescription.setVisible (false);
w.windowlist.setVisible(true);
if string.find(string.lower(w.name.getValue()), f, 0, true) then
return true;
end
return false;
end


If either one of the functions is commented out, then that function works (I can filter, or color the rows). If both functions are present....then I get a ton of script errors, but they appear to work. The error I get is:

Script Error: [string "reference_featgrouplistitem.featlist]:1: attempt to index field 'filter' (a nil value).

Tenian
November 11th, 2008, 18:29
I added


if not top.filter then
return true;
end

to the filter function and that removed the error and everything seems to work. Although I'm fuzzy at to why this is needed.

I also moved the alternating coloring into onListRearranged.

Everything sort of works....until you apply a filter. Applying the filter screws up the alternate coloring. So i tried to add the alternate coloring to the filter routine but it still doesn't work. I have a feeling I know why, but no clue how to fix it.

The alt coloring works on the entire windowlist, not just the list that's displayed after filtering. Ideally I would like to check the status of the item to see if it's displayed and then color based off this.....however I don't see any way to do that. There is no isVisible or isFiltered property for items within a windowlist that I can see.

Foen
November 11th, 2008, 22:34
A couple of points.

You might need the 'if not top.filter' test because of the order in which the lists and entries are created. If subsidiary entries are instantiated before the top level, the onInit calls may be invoked before top.filter is available.

Secondly, you could set a property on the entries from onFilter and then test it from onListRearranged:


function onFilter(w)
...
setFiltered(flag)
...
end

function onListRearranged(changed)
local alt = false;
for i,win in ipairs(getWindows()) do
if win.isFiltered() then
if alt then
win.setFrame("rowshade",0,0,0,0);
else
win.setFrame(nil);
end
alt = not alt;
end
end
end

Hope that helps

Foen

Bidmaron
November 12th, 2008, 01:04
Tenian, can you share the lines from your original linked table that you used (the one without the shading)? That is, can you share some of the rows in the native xml?
Also, would you mind posting the final result from all this effort. It looks imminently useful.

Tenian
November 12th, 2008, 02:48
I managed to get something working using an invisible number field to determine if the filter was active.

There's only one minor issue. Really I have a windowlist of windowlists. It is the deepest level that gets alternate shading. The second deepest level contains some header text.

When the filter is not active, this works great. However when the filter is active, the second deepest level headers are supressed and the lists run together (by design). Unfortunately this means it's possible for 2 shaded rows to end up next to each other. It's really a minor issue, and the new version is significantly better than the old one.

Bidmaron, what exactly are you after? The xml of one of the tabular lists?

Bidmaron
November 12th, 2008, 04:16
The table heading row and maybe just a few lines of the table. I am working on the FG2 Help module, and I may be able to use the technique in that module (or maybe not). Thanks.

Tenian
November 12th, 2008, 12:25
Well my generic sample module contains several tables. You can find one in the <weaponlistssample> block, but there are also examples for armor, equipment, magic items, and feats.

Since I build my lists automatically, Some tables have extra data at the table level which saves me the trouble of doing a database look up for all the values to be displayed in the table. If you are going to hand populate the XML, this is probably not something you want to do, as you'll be entering the data twice.

The reference_featlistitem does not have this extra data. You can see in it's onInit() function how it locates a database node and then does a look up for the table fields of prerequisite and shortdescription. It makes use of NodeManager.getSafeChildValue() which is a manager function which verifies a node exists and returns it's value, or returns a specified default.

The ruleset XML contained in the reference_*.xml files contain a lot of templates, manager functions, etc. You can get them all from the existing 4E_JPG ruleset if you need them.

You also notice there's a lot of repeated code between each list, this needs to be cleaned up, but I haven't gotten around to it.

Bidmaron
November 13th, 2008, 01:29
Tenian, God bless you. Thanks a lot! This is a boon.

Tenian
November 13th, 2008, 01:48
Actually moon_wizard has cleaned up my code some, the latest ruleset will have a version where the same functions aren't repeated in each list.

Functionally it's the same, he's just consolidated the code.