Bidmaron
December 2nd, 2017, 00:27
Modifications and Updates:
1: 12/2/17-Fixed the offset that was being determined when the drag was completed. Previously, the amount of growth/shrinkage of the control did not match the user's expectations based upon the visual distance between where he started and finished the drag. This has now been corrected in the lua file (attachment two below). No other changes are necessary.
This post describes a control template called the dragline that implements vertical resizing of the parent control (which should be vertically immediately above the dragline). In practice, the user can drag the dragline up to shrink the size of the control and down to increase the vertical size of the control. The dragline works in harmony with a scrollbar, as well. Based upon CoreRPG, the dragline should operate just fine with CoreRPG or any ruleset based upon CoreRPG.
As for the rest of the window below the dynamically-resized control, you have three options for this. For controls at the bottom of a window, you won't need to worry about any controls beneath. So, in this case, you won't need to do anything other than linking the resized control (called the parent) and the dragline, as I will explain below.
In the situation where your window form has a fixed amount of space you want to dedicate to a pair of vertically-stacked text boxes, you can place the dragline between them, and it will grow the top box and shrink the bottom box on a downward drag, or it will shrink the top box and grow the bottom box on an upward drag.
The last option is for all other situations and relies upon an anchor control below the dragline. If you use this option, the dragline will reposition the anchor control to follow the resizing of the dragline's parent control, and the remainder of the controls anchored to the anchor control will offset themselves accordingly.
To use the dragline, you will have to place an icon graphic file (provided below as vertical_size_arrows.png) into your extension folder and add a few supporting elements into your extension's xml file. First, to provide useful visual feedback to the user during the drag, you need to make an icon resource definition that invokes the icon graphic we spoke about:
<icon name="vertical_size_arrows" file="vertical_size_arrows.png" />
Second, you need to declare the control template for the control that will provide visual feedback to the user as they drag the dragline to resize the control(s) associated with the dragline. Place this xml template into your extension xml file somewhere:
<template name="dragger">
<genericcontrol>
<invisible />
<anchored position="insidetopleft" height="10" width="20" />
<icon>vertical_size_arrows</icon>
</genericcontrol>
</template>
The dragline script needs the control template in order to provide the visual feedback as we just discussed. The dragline completely handles instantiation of the control, as well as the display and operation of the dragger, so you don't need to worry about anything other than placing the control template into your extension xml file.
Third, to support the tooltip text for the dragline, you need to add the following string resource definition:
<string name="dragline_tooltip_dragparent">Drag this line upward to reduce the height of the field above or downward to increase the height</string>
<string name="dragline_tooltip_dragboth">Drag this line upward to reduce the height of the field above and reduce the height of the field below or downward to increase the height of the field above and reduce the height of the field below</string>
Fourth, you may need to setup the parent control, the one vertically above the dragline, to support some optional features of the dragline associated with the position and height of the parent control and the persistence of the height setting. If you do nothing to the parent control, it will always have a starting height of 20 pixels, and it will not remember any resizing the user performs after the window containing the dragline closes. To have the dragline start with a height other than 20, you will need to specify a height in the <anchor> tag of the control. You cannot do this through an attribute but must use a subtag. That is, you cannot use (for example):
<anchored position="insidetopleft" offset="5" height="60">
<right offset="-10" />
</anchored>
but must instead use:
<anchored position="insidetopleft" offset="5">
<height>60</height>
<right offset="-10" />
</anchored>
This is because FG's xml implementation at runtime does not encode attributes into the control data structure (this has the effect of reducing memory usage during execution but prevents control scripts from accessing potentially useful attributes [such as height, in this case]).
For a persistent method of height control (that is, the control remembers the last-dragged size), the dragline supports several options.
If the application for a dragline is such that you would expect all of the control's instances to be the same size no matter which window they are in, you can save the height setting in the campaign's registry by adding the following tag to the parent control's xml declaration:
<persist>campaign</persist>
or you can save the height setting in the user's registry by using this tag instead:
<persist>user</persist>
Using these first two options, note that each control on each window will have its own individual height that is shared across all of the windows using that individual control (that is, if you put the control into two different window specifications, the control will have two separately stored sizes, one for each window, but if say you are using the control in a customized version of the npc window, and you open five different NPCs using the window, all five will use the same height).
To have each usage of the control retain its own unique height setting after the window closes, use the following tag to store the height in the database along with the other window contents, and put it in every resizable control for which you want a separately stored value (for the curious, it will be stored in the campaign database in a field called 'height'):
<persist></persist>
If you want to control the name of the field used to store the height for some reason, place the name as the contents of the persist tag like this:
<persist>size</persist>
and the height will be retained as a first-level subnode of the database record associated with the window containing the control.
Here is an example of a vertically-resizable control from my Generators extension that uses all of these features:
<basicstring name="preprocessor">
<empty textres="generator_emptyforward" />
<anchored position="insidetopleft" offset="5">
<height>60</height>
<right offset="-10" />
</anchored>
<invisible />
<multilinespacing>20</multilinespacing>
<persist>ysize</persist>
</basicstring>
So, the first time the user ever opens a Generator window, the preprocessor field will have a vertical size of 60 pixels, but, after any user-resize operation, the database will store the size of the preprocessor window in the individual generator's ysize field, and the control will remember its last-set vertical size every time the user opens that generator's window.
The fifth thing you may want to do is provide a second vertically-resized control by using the <target> tag of the dragline. An example would look like this:
<target>secondcontrol</target>
If you don't want to control initial height or have any persistence of the control's height, you don't actually need to do anything to the second control because you do the setup for the second control in the dragline itself. Otherwise, insert the <height> subtag and/or the <persist> tag within your target control just like the parent control under step four.
Alternatively, if you want to have the controls beneath the resizing control to reposition dynamically with the resized control, you do so by identifying a <mooring> control in the dragline (see step six). This control need not be visible. An example might be:
<mooring>tabletoplabelanchor</mooring>
The sixth thing you have to do is to provide the dragline itself. It can be anwhere in the window definition because the dragline will anchor itself to its parent control. The only real requirement of the parent control is that it inherit from windowcontrol. However, the dragline is most useful if the parent control is a multi-line text box, including formattedtext. This is the template definition for a dragline control:
<template name="horizontal_dragline">
<genericcontrol>
<anchored height="5">
<top anchor="bottom" relation="absolute" offset="3" />
<left />
<right />
</anchored>
<frame name="quiescentdragline" />
<script>dragline_script.lua</script>
</genericcontrol>
</template>
This is continued in the next post.
1: 12/2/17-Fixed the offset that was being determined when the drag was completed. Previously, the amount of growth/shrinkage of the control did not match the user's expectations based upon the visual distance between where he started and finished the drag. This has now been corrected in the lua file (attachment two below). No other changes are necessary.
This post describes a control template called the dragline that implements vertical resizing of the parent control (which should be vertically immediately above the dragline). In practice, the user can drag the dragline up to shrink the size of the control and down to increase the vertical size of the control. The dragline works in harmony with a scrollbar, as well. Based upon CoreRPG, the dragline should operate just fine with CoreRPG or any ruleset based upon CoreRPG.
As for the rest of the window below the dynamically-resized control, you have three options for this. For controls at the bottom of a window, you won't need to worry about any controls beneath. So, in this case, you won't need to do anything other than linking the resized control (called the parent) and the dragline, as I will explain below.
In the situation where your window form has a fixed amount of space you want to dedicate to a pair of vertically-stacked text boxes, you can place the dragline between them, and it will grow the top box and shrink the bottom box on a downward drag, or it will shrink the top box and grow the bottom box on an upward drag.
The last option is for all other situations and relies upon an anchor control below the dragline. If you use this option, the dragline will reposition the anchor control to follow the resizing of the dragline's parent control, and the remainder of the controls anchored to the anchor control will offset themselves accordingly.
To use the dragline, you will have to place an icon graphic file (provided below as vertical_size_arrows.png) into your extension folder and add a few supporting elements into your extension's xml file. First, to provide useful visual feedback to the user during the drag, you need to make an icon resource definition that invokes the icon graphic we spoke about:
<icon name="vertical_size_arrows" file="vertical_size_arrows.png" />
Second, you need to declare the control template for the control that will provide visual feedback to the user as they drag the dragline to resize the control(s) associated with the dragline. Place this xml template into your extension xml file somewhere:
<template name="dragger">
<genericcontrol>
<invisible />
<anchored position="insidetopleft" height="10" width="20" />
<icon>vertical_size_arrows</icon>
</genericcontrol>
</template>
The dragline script needs the control template in order to provide the visual feedback as we just discussed. The dragline completely handles instantiation of the control, as well as the display and operation of the dragger, so you don't need to worry about anything other than placing the control template into your extension xml file.
Third, to support the tooltip text for the dragline, you need to add the following string resource definition:
<string name="dragline_tooltip_dragparent">Drag this line upward to reduce the height of the field above or downward to increase the height</string>
<string name="dragline_tooltip_dragboth">Drag this line upward to reduce the height of the field above and reduce the height of the field below or downward to increase the height of the field above and reduce the height of the field below</string>
Fourth, you may need to setup the parent control, the one vertically above the dragline, to support some optional features of the dragline associated with the position and height of the parent control and the persistence of the height setting. If you do nothing to the parent control, it will always have a starting height of 20 pixels, and it will not remember any resizing the user performs after the window containing the dragline closes. To have the dragline start with a height other than 20, you will need to specify a height in the <anchor> tag of the control. You cannot do this through an attribute but must use a subtag. That is, you cannot use (for example):
<anchored position="insidetopleft" offset="5" height="60">
<right offset="-10" />
</anchored>
but must instead use:
<anchored position="insidetopleft" offset="5">
<height>60</height>
<right offset="-10" />
</anchored>
This is because FG's xml implementation at runtime does not encode attributes into the control data structure (this has the effect of reducing memory usage during execution but prevents control scripts from accessing potentially useful attributes [such as height, in this case]).
For a persistent method of height control (that is, the control remembers the last-dragged size), the dragline supports several options.
If the application for a dragline is such that you would expect all of the control's instances to be the same size no matter which window they are in, you can save the height setting in the campaign's registry by adding the following tag to the parent control's xml declaration:
<persist>campaign</persist>
or you can save the height setting in the user's registry by using this tag instead:
<persist>user</persist>
Using these first two options, note that each control on each window will have its own individual height that is shared across all of the windows using that individual control (that is, if you put the control into two different window specifications, the control will have two separately stored sizes, one for each window, but if say you are using the control in a customized version of the npc window, and you open five different NPCs using the window, all five will use the same height).
To have each usage of the control retain its own unique height setting after the window closes, use the following tag to store the height in the database along with the other window contents, and put it in every resizable control for which you want a separately stored value (for the curious, it will be stored in the campaign database in a field called 'height'):
<persist></persist>
If you want to control the name of the field used to store the height for some reason, place the name as the contents of the persist tag like this:
<persist>size</persist>
and the height will be retained as a first-level subnode of the database record associated with the window containing the control.
Here is an example of a vertically-resizable control from my Generators extension that uses all of these features:
<basicstring name="preprocessor">
<empty textres="generator_emptyforward" />
<anchored position="insidetopleft" offset="5">
<height>60</height>
<right offset="-10" />
</anchored>
<invisible />
<multilinespacing>20</multilinespacing>
<persist>ysize</persist>
</basicstring>
So, the first time the user ever opens a Generator window, the preprocessor field will have a vertical size of 60 pixels, but, after any user-resize operation, the database will store the size of the preprocessor window in the individual generator's ysize field, and the control will remember its last-set vertical size every time the user opens that generator's window.
The fifth thing you may want to do is provide a second vertically-resized control by using the <target> tag of the dragline. An example would look like this:
<target>secondcontrol</target>
If you don't want to control initial height or have any persistence of the control's height, you don't actually need to do anything to the second control because you do the setup for the second control in the dragline itself. Otherwise, insert the <height> subtag and/or the <persist> tag within your target control just like the parent control under step four.
Alternatively, if you want to have the controls beneath the resizing control to reposition dynamically with the resized control, you do so by identifying a <mooring> control in the dragline (see step six). This control need not be visible. An example might be:
<mooring>tabletoplabelanchor</mooring>
The sixth thing you have to do is to provide the dragline itself. It can be anwhere in the window definition because the dragline will anchor itself to its parent control. The only real requirement of the parent control is that it inherit from windowcontrol. However, the dragline is most useful if the parent control is a multi-line text box, including formattedtext. This is the template definition for a dragline control:
<template name="horizontal_dragline">
<genericcontrol>
<anchored height="5">
<top anchor="bottom" relation="absolute" offset="3" />
<left />
<right />
</anchored>
<frame name="quiescentdragline" />
<script>dragline_script.lua</script>
</genericcontrol>
</template>
This is continued in the next post.