PDA

View Full Version : Dragline Control



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.

Bidmaron
December 2nd, 2017, 00:28
The following shows a dragline definition with the parent preprocessor control of the example above:


<horizontal_dragline name="drag_line">
<anchored>
<top>
<parent>preprocessor</parent>
</top>
</anchored>
<mooring>tabletoplabelanchor</mooring>
<tooltip textres="generator_tooltip_dragpreprocessor" />
</horizontal_dragline>

The last thing you must do is to include the following lua script file that implements all of the dragline functionality into your extension's folder ( provided as an attachment below).

Here is my complete window definition for the Generators extension that uses a resizable preprocessor box and the moored options (I omitted the script for the window, as it has no bearing on the dragline):


<windowclass name="table_main" merge="join">
<sheetdata merge="join">
<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>
<stringcontrol name="label_iterations">
<anchored to="label_output" width="20">
<top />
<left anchor="right" offset="10" />
</anchored>
<invisible />
<font>sheetlabelmini</font>
<static textres="generator_label_iteration" />
<tooltip textres="table_tooltip_iteration" />
</stringcontrol>
<scrollbar name="preprocessorbar">
<anchored to="preprocessor" />
<target>preprocessor</target>
</scrollbar>
<horizontal_dragline name="drag_line">
<anchored>
<top>
<parent>preprocessor</parent>
</top>
</anchored>
<mooring>tabletoplabelanchor</mooring>
<tooltip textres="generator_tooltip_dragpreprocessor" />
</horizontal_dragline>

<line_column name="divider3" />

<string_column_full name="postprocessor">
<empty textres="generator_emptyafterward" />
<invisible />
</string_column_full>

</sheetdata>
</windowclass>


Note that I am using window layering over the standard CoreRPG tables window, so most of the actual screen elements are not the window defintion above (if you don't know what layering is, it is like a more advanced form of template inheritance, but you need not worry about it. The dragline will work in any window containing controls).

Here is how the Generator window looks with the 60 height specified. The generator you see in the window is a nonsense generator I am using simply to test my code, so please ignore the bogosity in the table elements themselves.

21636

Here is a screenshot showing the tooltip if the user hovers over the dragline:

21637

Here is a screenshot showing the user performing a drag of the dragline to increase the size:

21638

Note the dragger control attached to the cursor that gives the user visual feedback on the drag itself.

Here is a screenshot showing the window after making the preprocessor taller:

21639

If you run into any problems, let me know in this thread, and I will respond. If it is a problem with the code itself, I will look into it and post a fix when I can get around to it.

If there are any other features you'd like, post me in this thread, and I will take it under advisement.

In the future, I intend to develop a window column resizing tool that will do horizontally what the dragline does vertically in most respects. Let me know in this thread if there are any features you'd like to see in that. Currently, I plan to have it grow one column at the expense of the column on the other side of the verticaldrag, or, if you hold down control, have the column to the left grow or shrink and the window width changes accordingly.

Bidmaron
December 2nd, 2017, 02:57
Currently, the drag does not register the vertical distance correctly, and I have not figured out the reason for the inaccuracy. It appears that the distance is consistently 5-10 pixels too high on screen. So, when you drag down, it doesn't grow enough, and when you drag up, it shrinks too much.
Fixed 12/2/17 0030

No other known issues.

Bidmaron
December 2nd, 2017, 04:26
Possible improvements/adds/changes:
Double-clicking the drag-line auto-sizes the parent control so that all contents exactly fit in the control.

damned
December 2nd, 2017, 05:18
Currently, the drag does not register the vertical distance correctly, and I have not figured out the reason for the inaccuracy. It appears that the distance is consistently 5-10 pixels too high on screen. So, when you drag down, it doesn't grow enough, and when you drag up, it shrinks too much.

No other known issues.

Try using a taller drag graphic and see if that effects this offset? Maybe its basing the offset from a particular part of the graphic?

Bidmaron
December 2nd, 2017, 05:28
I fixed it. The problem was that the drag implementation requires that you offset the mouse a small amount before it considers a drag to have begun. As a result, my starting coordinates were never right because the drag start did not happen where the user perceived but where the system registered start of drag.

To fix it, I had to add onHover and onHoverUpdate handlers to record the actual mouse starting location for the drag. I will repost the script file tomorrow.

Minty23185Fresh
December 2nd, 2017, 06:58
Nice. Thank you. I can't wait to give it a go.

Bidmaron
December 2nd, 2017, 13:22
Minty, it really is not as complicated as all this thread may make it seem. It is basically like adding any other template-based control: You create the control inheriting the template, tweak the xml tags, add the files provided into your extension, make a few xml declarations, and you are in business. Once you use the first dragline, it is then very easy to use it again.

damned
December 2nd, 2017, 13:59
Its always nice to make things do something that no one has made them do though... :)

Minty23185Fresh
January 13th, 2018, 19:34
Bidmaron.

Thank you again for engineering this control. I am finally getting around to employing it within my extension.

I would like to ensure you get credit for your work and so would like to place crediting (and copyright?) information in any and all files specific to the dragline, either .xml or .lua, that I add to implement the control. Would it be possible to provide the text you'd like me to place as a header comment in the files?

Bidmaron
January 13th, 2018, 20:32
Minty, my friend, just use it. I didn’t do it for credit. Now if you insist, just say based on Bidmaron’s dragline control but my work is for the community.

Bidmaron
January 14th, 2018, 18:39
I just fixed one error in the original post because the include file for the dragline lua code was the wrong name in the template. Thanks, minty for pointing this out.

Minty23185Fresh
January 24th, 2018, 05:52
The author of the control, Bidmaron, developed the control using text based controls (stringcontrols).

My intention is to use the Dragline Control with Windowlists rather than Stringcontrols. I am just about there but I have run across a "strangeness" with scrollbars. When the dragline is dragged sufficiently far, causing a windowlist to shrink in height, it's associated scrollbar will eventually become invisible.

It's my assumption that: If a scrollbar is made too short, so that it can no longer resolve the items in say a list or a multiline textbox, the scrollbar fails and becomes invisible.

Does anyone know if this statement is true?

A visual example might help. I'm using the CoreRPG ruleset. I am adding additional functionality (plus the Dragline Control) to my Field Filters for All Libraries Extension. The following panels show the NPC Library Editor. There are two windowlist controls, a list of NPCs in the upper portion and the field filter list in the lower portion. Each list contains six items; all six are displayed in the upper portion only five are displayed in the lower portion, but there is a scrollbar available to gain access to the sixth item of the lower list. The Dragline Control is a very thin gray line right at the bottom of the upper list's frame.

In the screenshots below, the first, left most panel, depicts the editor at startup. The second panel shows the editor after I have dragged the Dragline Control up about 1/4 of the dialog's height. The upper list shows only four items, but has a scrollbar to access the other two items. The lower list now displays all six items and no scroll bar is displayed (because the windowlist is now of sufficient height to display all items in the list, a scrollbar is not necessary). The blank area below the lower list is the additional, unused area of the heightened second list. For the third panel, upper right, I dragged the Dragline up to the point that the scrollbar for the upper list failed and disappeared (highlighted with the red rectangle). Then I dragged the Draglne downward sufficiently to cause the scrollbar for the lower list to fail and disappear. Finally, in the fifth panel, I dragged the dragline up just the tiniest bit, such that the scrollbar became visible, but notice how the scrollbar's slider takes up nearly all of the scrollbar's height. Trying to use the slider to manipulate the list to the desired item is nearly impossible. This is what led me to believe that if the scrollbar length is too short, such that the slider cannot be used to accurately run through the items, it fails and disappears. (Note that there were no error indications thrown to either the Chat or the Debug.console when the scrollbar failed to display.)

In this particular instance, a height of two list items seems to be the cutoff. If the list is collapsed to two or less items the scrollbar fails.

21997

For a user of an extension that employs the Dragline Control, having no scrollbar to access the complete list is unacceptable behavior (let alone it would probably be confusing to the user). To circumvent this issue I plan to add sufficient lua script to prevent the user from dragging the Dragline to extremes that would collapse either list to less than three list items high.

Bidmaron
January 24th, 2018, 06:06
Minty, I am seeing the same behavior just in a text control that the scrollbar vanishes if you shrink less than 3 lines. Now in a text box, that isn't much of a big deal because you can just put the cursor in the box and arrow up and down to see all the contents. Of course, you have to have the window unlocked for editing to do that. In a window list, that might not be so easy to see everything....

I think your solution of not shrinking that small is a good one, but you might want to let him shrink to no less than 3 lines or the number of lines in the window (if there are only 2 lines, why can't he shrink to 2 lines).

By the way, Minty, I haven't gotten to your list of stuff in this thread that I should fix. Hopefully, this weekend.

Minty23185Fresh
January 24th, 2018, 06:18
Thanks Bidmaron. Good to hear that I'm not the only one experiencing this issue.

And true, no scroll bar is needed if the list only has one, two or three items, so shrinking to those (special) heights would be permitted.

And no rush on my account to address those other items. As you can see I'm well underway given the help you've already provided. Thanks.

Bidmaron
January 24th, 2018, 12:24
No sweat. Glad to have helped.

Minty23185Fresh
February 5th, 2019, 23:37
Things are so easily forgotten in the day-to-day. It is high time I express the kudos deserved for this control. It has been in use in my Field Filters extension for over a year now, without a hitch!

Thanks so much Bidmaron for this control and for your patience and persistence in getting it going in my project.

Bidmaron
February 6th, 2019, 04:51
No sweat at all, Minty. Now if we could just get MW to put it into CoreRPG....
I need to get around to making a vertical corollary to it, but my danged job has me working ridiculous hours (last week I never went to sleep two nights working 36 hours straight - insane).