PDA

View Full Version : Bidmaron's Coding Questions



Bidmaron
April 5th, 2014, 14:32
Suppose I have a utility window class (Question) that uses a lua script file (code_Question.lua). Now, suppose I also define Code_Question as a code library (QuestionLib) using the syntax below:

<script name="QuestionLib" file="scripts/code_Question.lua"/>

When you instantiate a window with the window class, does the script file get its own environment for that window? In other words, do local variables declared there only apply to the window instantiation or do they apply across all windows of that class?

Related, when I invoke a function in my library, does it access these shared local variables or is that a separate, unique code library instantiation?

The burning question arising from this is: when does onInit get called?
Does it get called upon loading as a library?
Does it get called when the window is instantiated?
Does it get called for both?

Bidmaron
April 5th, 2014, 15:37
I have to implement an asynchronous dialog window in ModPlus, so I need a callback mechanism. I am still fuzzy on which portions of lua are implemented in FG and which are not.

In normal lua, I could call a dialog routine with a function as a parameter. Inside my dialog routine, I could save this function to a variable and then, when the user completes action in the window and selects an okay or cancel button, I could then invoke the function in this variable.

Will this construct work in lua as FG implements it? The workaround is really ugly and inelegant.

Trenloe
April 5th, 2014, 16:28
Suppose I have a utility window class (Question) that uses a lua script file (code_Question.lua). Now, suppose I also define Code_Question as a code library (QuestionLib) using the syntax below:

<script name="QuestionLib" file="scripts/code_Question.lua"/>

When you instantiate a window with the window class, does the script file get its own environment for that window? In other words, do local variables declared there only apply to the window instantiation or do they apply across all windows of that class?
It gets its own environment. Local variables apply only to each window instance or the library.


Related, when I invoke a function in my library, does it access these shared local variables or is that a separate, unique code library instantiation?
It is separate.


The burning question arising from this is: when does onInit get called?
Does it get called upon loading as a library?
Does it get called when the window is instantiated?
Does it get called for both?
onInit gets called each time the new script environment is created - when you define QuestionLib and each time a windowclass with the script attached is created.

So the answer is yes to all of your questions.

Essentially, think of it this way: each time you have file="scripts/code_Question.lua" anywhere within your XML, this script file will create it's own environment (and run onInit for that environment only). You can access functions and non local variables from externally to the environment with either QuestionLib.XXX or <windowclassname>.XXX, where XXX is the function name or the hierarchical <windowclass> name.

EDIT: and if file="scripts/code_Question.lua" is in a template, there will be a new script environment created each time an object using that template is created.

Bidmaron
April 5th, 2014, 16:39
Thanks, Trenloe. I had to split the code into two files because I couldn't figure out a way to tell whether onInit was being invoked on loading the code library or on loading a form. Plus, there was just no reason to share the code in a single file.

Do you know anything about my second question in post #2?

Trenloe
April 5th, 2014, 17:09
In normal lua, I could call a dialog routine with a function as a parameter. Inside my dialog routine, I could save this function to a variable and then, when the user completes action in the window and selects an okay or cancel button, I could then invoke the function in this variable.
Yeah, you should be able to do this.

Bidmaron
April 5th, 2014, 17:23
Thanks again, Trenloe.

Bidmaron
April 6th, 2014, 14:23
Has anyone developed a method to walk the window instances in z order?

Here's the challenge I'm trying to solve:
For ModPlus to let the GM configure which individual fields that a player can edit (also with control over whether GM must approve and whether GM should have a flag for changed fields) [for character sheets, there are two different modes - one for what the player can edit during game and another for what he can edit locally on an exported sheet], I am having it where if you hold down the alt key over a window (GM-only windows excluded of course, as well as those like image windows, where the player edits, where permitted already have a permission ability [moves of tokens]), widgets will show up on each control showing the editability of each field. The GM can then click on the widget/button to alter the editability of that field. (for lists, I currently think the way to regulate editability of added items is to register the editability on the add/edit button of a list, but I'm looking for a better idea if anyone has it)

Current method that I see as only way possible to implement:
* Override all window classes of interest as follows:
onHover - use to detect that the user is over the window and alter a global variable as to the current window (if any) that the user is over. Invoke any super and self onHover routines that may exist to prevent stomping existing code.
* Intercept the Interface.onAlt event (it sure would be nice if this were a handler so I wouldn't prevent anyone else from using this event) to see if there is a window registered and, if so, either display or hide and disable all the edit control buttons.

For the initial implementation, I'm not going to permit editing (GM or not) of library items, although, as I've said before, I plan to do this using my Background program to handle library edits downstream.

Moon Wizard
April 6th, 2014, 22:44
Input.onAlt is a handler, which means that any number of scripts may register for this event.

There's no specifically defined method to walk the Z-order. I believe from the list of windows returned by Interface.getWindows is in Z-order from what I can tell. You just need to make sure that you use numerical indexes or ipairs to access the window list.

Regards,
JPG

Bidmaron
April 12th, 2014, 22:24
The template "footer" is used in several places in CoreRPG, but it is not defined there (or at least that Notepad++ can find), nor is it in the documentation on-line. Anyone know where it is defined?

Trenloe
April 12th, 2014, 22:49
<footer> is not a template, it is a tag used in <windowlist> and <formattedtextcontrol> controls. Consult the reference doc for those 2 controls.

Bidmaron
April 12th, 2014, 23:15
Oops. Thanks. OK, make me an idiot again:
'center' is used extensively in template_common.xml, but I can't find that documented in either the windows and controls generic documentation or in windowcontrol. Where exactly can center be used (I know there is an align tag that has center as an option for tooltips, but can't find it anywhere else).

Trenloe
April 12th, 2014, 23:28
It is usually part of a <stringcontrol> (or a label template defined using <stringcontrol>), which inherits <textbasecontrol> which is where <center> is defined.

Follow the template definitions and element hierarchy and ye shall find! :)

Bidmaron
April 12th, 2014, 23:33
Got me again. I did check stringcontrol, just didn't go deep enough!

Bidmaron
April 13th, 2014, 15:23
I'm having trouble understanding the sub window documentation.
Docs say:

Inherits windowcontrol
Context windowinstance
This control is a container and viewing port for a windowinstance object. The created window will always have the same data source as the parent window. By default, the windowinstance object will not be instantiated until the control is visible on screen. (See fastinit tag below)

Using the positioning and sizing functions for the contained windowinstance may have unpredictable results. If resizing of the windowinstance is desired, the size of the parent subwindow control should be changed instead.

A reference to the contained windowinstance object is available from the script environment of the parent subwindow control through the variable subwindow. In the other direction, a reference to the parent subwindow control is available from the contained windowinstance object through the parentcontrol variable.



Definition


<subwindow name="..." >
<class > ... </class> The name of the window class used to create the window
<activate /> If specified, show the control. By default, the control is hidden.
<fastinit /> If specified, instantiate the windowinstance when this control is created. Otherwise, the windowinstance will not be instantiated until control is drawn on screen.
</subwindow>

Interface


onInstanceCreated


event function onInstanceCreated( )
If present, this function is executed when the window instance contained in the subwindow has been created.



If you don't put in the activated tag, what activates the sub window?
Fastinit is really confusing. What happens without it, and what happens with it? (I see that without fastinit, the instantiation occurs when it becomes visible, but what is the difference since a window itself doesn't get instantiated until it's visible (well, I guess you could create it invisible).
Subwindows have their event onInstanceCreated and the parent windowInstance has its own event onSubWindowInstantiated (which states that it executes after the onInit [presumably of the window class of the sub window]). What is the relative order in which these are invoked? Obviously, the onInstanceCreated goes in the script tag (or file) for the sub window in the sheet data where the sub window is used, and the onSubWindowInstantiated goes in the script tag (or file) for the containing window (right?).

The docs say using the position and size can be unpredictable. What is the workaround? My application has a variable number of the same class of sub window, and I need to handle anchoring by setting position because addControl is used to add the sub windows, and I don't think relative anchoring will work for controls added in the onInit for the containing window (or does it?).

Moon Wizard
April 14th, 2014, 22:57
Originally, subwindows were built as a way to implement tabbed sheets. Since then, they have been improved to be used in other scenarios.

By default, the subwindow control is invisible. If the activate tag is used, then the control will be visible. This is the reverse of how every other window control works, but has been maintained for backward compatibility.

Also, by default, the window instance within a subwindow control is not instantiated until it is drawn (i.e. subwindow is visible and draw event called). The "fastinit" tag forces instantiation of the enclosed window instance when the control is created before the onInit event for the control is called.

The onInstanceCreated and onSubwindowInstantiated events were added to allow ruleset creators to capture when the window instance was actually created within a subwindow. The event can either be captured in the encapsulating subwindow control (onInstanceCreated) or in the created window instance (onSubwindowInstantiated).

Ultimately, the layout of a window within a subwindow control depends on many factors, but primarily the layout of the subwindow control and the requirements of the contained window instance. To start with, the window instance is given the area of the subwindow control as it's default area. Next, the window class minimum and maximum size are applied. Then, all the controls for the embedded window instance are laid out within this area. Controls can be defined outside of the viewable area of the subwindow, which means that the embedded window instance size is increased to accommodate. Finally, the window class minimum and maximum size are applied again. If the subwindow width or height is undefined, then the window instance will define the width/height. If the resulting size of the embedded window instance is greater than the subwindow control, then the subwindow becomes a scrollable control that is a viewport onto the embedded window instance.

If you are adding multiple subwindows that are visible at the same time (unlike tabbed windows), then it seems like you would need to specify relative anchors. They could be defined in the template, as long as the anchor point is fixed.

Regards,
JPG

Bidmaron
April 15th, 2014, 03:29
Thanks, JPG. This is an excellent and informative treatment about many things (capture in wiki?).

My problem is that the number of sub windows is dynamic. Currently, I've gotten rid of the sub windows and am adding controls dynamically. I can't get relative to work when adding controls using createControl, so I'm having to do the resize in the individual controls (I hope that works).

Bidmaron
April 20th, 2014, 14:00
I cannot find any examples of where relative positioning is used in both vertical and horizontal dimension. I'd ask that someone in the know, confirm my supposition below:

You cannot use the relation tag in more than one anchor tag set (which begs the question: If you screw up and do so, which one takes precedence, first or last?)
The reason for this is because the system only registers the relation tag value one time and applies it in both the x and y direction if the relation value is 'relative.'


The reason I'm asking this is because what I wanted to be able to do was to use the relation="current" for a control on a row of controls but to position that control under anchorcolumn (defined as is standard for FG to be below the window title and near left edge of useable frame and the width of useable frame) and use the parent as anchor column in both the <top ... /> and <left .../> tags.
Perhaps I'm screwing something up, but the only way I can get the control to show up is to use parent only in <top .../> and then use frame-relative positioning in the <left .../> tag (i.e. don't put in a parent attribute in the <left .../> tag).
This works, of course, but it limits reusability of items because you build a frame dependency into the template that you shouldn't have to do.

Anyway, please let me know if my analysis is correct. Wrapping one's head around control and window tags is, to me, one of the hardest things about coding for FG.

Trenloe
April 20th, 2014, 17:18
I'm not sure what you're actually trying to do. Could you provide some sample XML definitions? In a usable format would be great - i.e. that can be tested easily in FG.

Bidmaron
April 20th, 2014, 17:30
Thanks for replying Trenloe. I have my code working, but I could not get the tag to work on more than one of the four ordinals (left, top, right, bottom). As with many things in FG, there are usually more than one way to do something.

Bidmaron
April 24th, 2014, 02:36
How can I get the user name for the user as he reports himself when he logs into the game? Right now, the docs say:

getUsername


function getUsername( )
Returns the local user's network username.

Return values

(string)
The username string


I don't want the network username but the name he logged into FG with. I see not function to obtain that.

Trenloe
April 24th, 2014, 05:24
How can I get the user name for the user as he reports himself when he logs into the game? Right now, the docs say:

getUsername


function getUsername( )
Returns the local user's network username.

Return values

(string)
The username string


I don't want the network username but the name he logged into FG with. I see not function to obtain that.
The name that User.getUsername() returns is the "Username" entered on the "Join Game" screen.

Trenloe
April 24th, 2014, 05:34
How can I get the user name for the user as he reports himself when he logs into the game?
Or use the onLogin event - this gives the username with the event: https://www.fantasygrounds.com/refdoc/User.xcp#onLogin

Bidmaron
April 27th, 2014, 02:24
With trying to support internationalization, I'm running into problems. I have three controls I need to place side-by-side. First is a checkbox (my other question in Merge rules pertains), then a label string, and a stringcycler. The stringcycler contents and the label need to use string resources. It is easy to align the label to the checkbox. But how do I align the cycler to the label without a gap?

When I look at windowcontrol, it provides a minimum sizelimit tag. If I specify that, will the label auto-adjust the control width so I can anchor the cycler to the right edge of the label?

Bidmaron
April 30th, 2014, 02:59
I have tried to adjust a window height by calling setSize within the window's onInit event, but it is not working. Is there a prohibition on setting window size within its onInit event? I have debugged the routine and confirmed that the size I am setting exceeds the current size, but the window remains the same size.

Bidmaron
April 30th, 2014, 22:34
OK, found my own answer. To have the window resize as it is populated, you have to eliminate the appropriate dimension from the <placement> tag. Thus, if you want the window to expand or shrink vertically, don't put in the height tag. If you want the width fixed, enter the value you want, usually the frame width.