i'm thinking it might be nice to have a function to add padding to each side/top/bottom between the frame border and the column/row data. then the user could simply ask for padding at the top of the frame to put the border around the frame headers or ask for more on the right to capture the scrollbar in the frame.
I've been thinking about draggable column widths and what I would do in the case of resizing the table width wise is let you specify 1 column with a dynamic width. That would be, by far, the easiest and least destructive method of implementing it.
Showing more rows for vertical resizing also seems doable.
Its doable until you start to realize you need more than 100 lines of code for the resizing grips, which has to take into account overall scale, the grip's scale, the parent's scale, the x/y offset, the minimum size of itself + neighbouring columns and code OnHide to stop moving the grip (because the parent can get hidden, say on ESC press), the resizing and reanchoring code for the text.
I know this firsthand after doing Omen3's vertical resizing grips.
Its doable until you start to realize you need more than 100 lines of code for the resizing grips, which has to take into account overall scale, the grip's scale, the parent's scale, the x/y offset, the minimum size of itself + neighbouring columns and code OnHide to stop moving the grip (because the parent can get hidden, say on ESC press), the resizing and reanchoring code for the text.
I know this firsthand after doing Omen3's vertical resizing grips.
the resize i was requesting wasn't giving scrolling tables ui controls, etc. i was talking about the likelihood that a scrolling table would be placed in a frame that is resizable (with all the gui methods to handle it) and how the st should respond to a its frame suddenly changing shape.
It should resize itself, and all its internal text label widths should just multiply by a constant (newwidth/oldwidth), so maintain a copy of the current width somewhere of the whole table.
It should resize itself, and all its internal text label widths should just multiply by a constant (newwidth/oldwidth), so maintain a copy of the current width somewhere of the whole table.
i think that's certainly an option for a horizontal rescale, but a different option would be to have one column be dynamic and the others remained locked. like say in the case where you have fields that you know roughly how big they'd ever be (player name, skill level, class, race) plus another field that is less well defined (notes). you could allow resizes on your window to expand the notes field so people could see excessively long notes without having a bunch of space introduced around the toon's level which would never need the extra space.
the min/max idea i posted earlier would let you define it however you wished, but i suppose might be more complicated than necessary.
i think mikk might be onto something with a function to reset widths. this would allow as much complexity as the author desires without having to support all flavors in the base library.
not sure i would do it as a return sequence, tho. i'd probably just operate on the header table itself.
optionally, in keeping with the style of the rest of the system (ie, overloaded variables) maybe allow a function in place of a static width parameter. you might need/want to then add an internal sense of just how wide the overall table wants to be (the frame size minus any padding).
so i'm having an instance where i want to have a column that represents time formatted in a human readable way (1 day, 4 hours for example). of course, this messes up sorting since the sort is alphabetical. i propose an additional field to the column data table -- "display" which if present would act as the value field purely for the display and value would be used for any sorting. if display is unset, then value is used for display as well.
sparky, as for the time concern... would having a comparator function supplied during the column definition be ok with you? or do you need something more?
Right now I have a basic comparator function that I'm using, you would have to model it after mine I suppose to take into account possible values being functions, or if you knew they weren't then not bother. the comparator is a built-in component to the table.sort, so I would just pass it along. when compare(a, b) comes in, a and b are the cells, so you could stick the timestamp as a number in an unused member of the table... i.e
cell.value
cell.timestamp <---
That way your function would know that the column is being sorted by timestamp.
Also, please create an enhancement request ticket on the project page so i can keep track of this and not forget.
sparky, as for the time concern... would having a comparator function supplied during the column definition be ok with you? or do you need something more?
Right now I have a basic comparator function that I'm using, you would have to model it after mine I suppose to take into account possible values being functions, or if you knew they weren't then not bother. the comparator is a built-in component to the table.sort, so I would just pass it along. when compare(a, b) comes in, a and b are the cells, so you could stick the timestamp as a number in an unused member of the table... i.e
cell.value
cell.timestamp <---
That way your function would know that the column is being sorted by timestamp.
Also, please create an enhancement request ticket on the project page so i can keep track of this and not forget.
i'm using the library and what i've done is added a "display" field that acts exactly like the value field (if it's a function then it evaluates using the arg field a la value). if that field exists when it's time to show the button, it will use it instead of the value field. it seemed like the simplest way to deal with it.
i suppose another option would be to have a "sort" field that would be the same thing, only in reverse -- it would be used (if found) in any sort comparison functions, otherwise it would fall back to the value field.
yet another option, would be to provide an overload on the display function itself (normally self:SetText(...)) if you give it a function to use when it comes time to show this value, then it would use that instead of just a simple SetText() this might actually be a good way to provide a hook into the system as well so people could do whatever they want on a button at draw time.
and of course, there's also the way you suggest. i guess the question becomes what provides the most bang for the buck in terms of additional complexity. i'd personally lean towards the SetText overloading (even tho i did something different already). this gives you the option to do all sorts of stuff without having to add much code at all.
i've also made a few other changes to the code, so if you'd like, i can send them over to you. in experimenting with trying to get the system to handle resizes, i found a lot of buttons being recreated and since ui elements cannot be destroyed, it was not pleasent.
here's my modified core.lua file. wasn't sure how else to get it to you.
in my main app i'm doing this:
function GYP:OnResize()
if GYP.st then
local rows = floor((GYP.frame:GetHeight()-60-15) / 15)
GYP.st:SetDisplayCols(GYP.st.cols);
GYP.st:SetDisplayRows(rows, GYP.st.rowHeight);
GYP.st:Refresh()
end
end
the SetDisplayCols and SetDisplayRows used to not be very happy about being called multiple times, so i changed that and reworked a bit of the logic in the DisplayRows function to create new rows as needed and to hide() those no longer being used.
i added that "display" field i was referring to before, but i dunno if that's the best solution anymore.
i added the ability to set "width" as a function to be called instead of a single scalar. didn't really get into what args would be passed to the function...
This means that you can register any event you like, but you do not have to define them per cell/row. You define them once per table (you can redefine them later as well) and handle the logic for cell/row yourself within the event handler.
wasn't sure what the new event system would have in store, but it seems to work well.
i ended up keeping my basic system in place and just registered the following as my OnClick:
st:RegisterEvents({
["OnClick"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, ...)
local cellData = data[realrow].cols[column]
if cellData.onclick then
cellData.onclick(unpack(cellData.onclickargs or {}))
else
if cols[column].onclick then
cols[column].onclick(unpack(cellData.onclickargs or cols[column].onclickargs or {}))
end
end
end,
});
basically, that makes the old system of "onclick" work with the new system without any changes. plus, it lets you register a single "onclick" function at the column header level (the argument to SetDisplayCols) as a fallthru in case no onclick function exists on the cell. if the args exist on the cell, it uses them, otherwise it uses the args from the cell header (altho this maybe should be the value from the cell).
okay, so i've updated everything to work with the new version.
i posted a couple of tickets on some specific problems (endless loop and memory leak).
there's also some issues in the SetDisplayCols() function that make it unhappy when called over and over -- namely the recreation of frames/buttons/fontstrings that already exist and the forced initialization of the row.cols table.
i need to call this function when i resize my window to adjust widths for columns. seems like a lot of work just to make a simple "setwidth" call, so maybe there's a better way to handle it.
i like the adjustment you made to the scrollbar -- that it's inside the frame (i was actually hacking things to make it work this way in my mod before you changed it). but it should turn off if the # of filtered rows is less than the # of display rows. it doesn't show up until it needs to, but once it's there it won't go away automatically and the OnHide forces a Show() so i can't do it manually.
The only problem was trying to resize everything when it wasn't showing.
Having the extra space there is annoying when you dont have to scroll...
I'll take a look. I liked the disabled look when you didnt have to scroll, but I can see people might like it to go away.
basically, that makes the old system of "onclick" work with the new system without any changes. plus, it lets you register a single "onclick" function at the column header level (the argument to SetDisplayCols) as a fallthru in case no onclick function exists on the cell. if the args exist on the cell, it uses them, otherwise it uses the args from the cell header (altho this maybe should be the value from the cell).
Good. This is what I had in mind.
Now users can register a handler for any event they actually want to support, instead of the library trying to guess.
Sounds fantastic, I could definitively use this but i'm going to wait until I see some code samples before I try it. Current documentation confuses me more than it explained usage tbh.
I came across this library and would like to play a little bit with it but some things seem weird to me :
1/ the way you seem to use it in your DKP addon is by not embedding it (I guess you have a standalone version), any particular reason ?
2/ I have very specific needs, I'm trying to display reports that have a varying number of lines AND columns, does that mean that I should recreate a new instance each time I want to change the columns ?
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
Its doable until you start to realize you need more than 100 lines of code for the resizing grips, which has to take into account overall scale, the grip's scale, the parent's scale, the x/y offset, the minimum size of itself + neighbouring columns and code OnHide to stop moving the grip (because the parent can get hidden, say on ESC press), the resizing and reanchoring code for the text.
I know this firsthand after doing Omen3's vertical resizing grips.
the resize i was requesting wasn't giving scrolling tables ui controls, etc. i was talking about the likelihood that a scrolling table would be placed in a frame that is resizable (with all the gui methods to handle it) and how the st should respond to a its frame suddenly changing shape.
i think that's certainly an option for a horizontal rescale, but a different option would be to have one column be dynamic and the others remained locked. like say in the case where you have fields that you know roughly how big they'd ever be (player name, skill level, class, race) plus another field that is less well defined (notes). you could allow resizes on your window to expand the notes field so people could see excessively long notes without having a bunch of space introduced around the toon's level which would never need the extra space.
the min/max idea i posted earlier would let you define it however you wished, but i suppose might be more complicated than necessary.
Without having the first idea of what the syntax is (i'm just butting in here):
Lib.MakeScrollingTable(some,data,here,
function(totwidth) return 100,50,250,width-400 end
)
Tadaa?
<FRAMESET cols="20%,30%,50%">
<FRAMESET cols="100,*,100">
<FRAMESET rows="30%,400,*,2*">
http://www.w3.org/TR/WD-frames-970331
not sure i would do it as a return sequence, tho. i'd probably just operate on the header table itself.
optionally, in keeping with the style of the rest of the system (ie, overloaded variables) maybe allow a function in place of a static width parameter. you might need/want to then add an internal sense of just how wide the overall table wants to be (the frame size minus any padding).
Are all of you using the library?
I'll start working on this again soon, but feel free to supply any patches if I'm taking too long :)
Had a really fun trip to 80.. so much to do!
Right now I have a basic comparator function that I'm using, you would have to model it after mine I suppose to take into account possible values being functions, or if you knew they weren't then not bother. the comparator is a built-in component to the table.sort, so I would just pass it along. when compare(a, b) comes in, a and b are the cells, so you could stick the timestamp as a number in an unused member of the table... i.e
cell.value
cell.timestamp <---
That way your function would know that the column is being sorted by timestamp.
Also, please create an enhancement request ticket on the project page so i can keep track of this and not forget.
i'm using the library and what i've done is added a "display" field that acts exactly like the value field (if it's a function then it evaluates using the arg field a la value). if that field exists when it's time to show the button, it will use it instead of the value field. it seemed like the simplest way to deal with it.
i suppose another option would be to have a "sort" field that would be the same thing, only in reverse -- it would be used (if found) in any sort comparison functions, otherwise it would fall back to the value field.
yet another option, would be to provide an overload on the display function itself (normally self:SetText(...)) if you give it a function to use when it comes time to show this value, then it would use that instead of just a simple SetText() this might actually be a good way to provide a hook into the system as well so people could do whatever they want on a button at draw time.
and of course, there's also the way you suggest. i guess the question becomes what provides the most bang for the buck in terms of additional complexity. i'd personally lean towards the SetText overloading (even tho i did something different already). this gives you the option to do all sorts of stuff without having to add much code at all.
i've also made a few other changes to the code, so if you'd like, i can send them over to you. in experimenting with trying to get the system to handle resizes, i found a lot of buttons being recreated and since ui elements cannot be destroyed, it was not pleasent.
in my main app i'm doing this:
the SetDisplayCols and SetDisplayRows used to not be very happy about being called multiple times, so i changed that and reworked a bit of the logic in the DisplayRows function to create new rows as needed and to hide() those no longer being used.
i added that "display" field i was referring to before, but i dunno if that's the best solution anymore.
i added the ability to set "width" as a function to be called instead of a single scalar. didn't really get into what args would be passed to the function...
http://www.wowace.com/projects/lib-st/tickets/7-rightclick-events-do-not-work/
This means that you can register any event you like, but you do not have to define them per cell/row. You define them once per table (you can redefine them later as well) and handle the logic for cell/row yourself within the event handler.
i ended up keeping my basic system in place and just registered the following as my OnClick:
basically, that makes the old system of "onclick" work with the new system without any changes. plus, it lets you register a single "onclick" function at the column header level (the argument to SetDisplayCols) as a fallthru in case no onclick function exists on the cell. if the args exist on the cell, it uses them, otherwise it uses the args from the cell header (altho this maybe should be the value from the cell).
i posted a couple of tickets on some specific problems (endless loop and memory leak).
there's also some issues in the SetDisplayCols() function that make it unhappy when called over and over -- namely the recreation of frames/buttons/fontstrings that already exist and the forced initialization of the row.cols table.
i need to call this function when i resize my window to adjust widths for columns. seems like a lot of work just to make a simple "setwidth" call, so maybe there's a better way to handle it.
i like the adjustment you made to the scrollbar -- that it's inside the frame (i was actually hacking things to make it work this way in my mod before you changed it). but it should turn off if the # of filtered rows is less than the # of display rows. it doesn't show up until it needs to, but once it's there it won't go away automatically and the OnHide forces a Show() so i can't do it manually.
Having the extra space there is annoying when you dont have to scroll...
I'll take a look. I liked the disabled look when you didnt have to scroll, but I can see people might like it to go away.
Good. This is what I had in mind.
Now users can register a handler for any event they actually want to support, instead of the library trying to guess.
1/ the way you seem to use it in your DKP addon is by not embedding it (I guess you have a standalone version), any particular reason ?
2/ I have very specific needs, I'm trying to display reports that have a varying number of lines AND columns, does that mean that I should recreate a new instance each time I want to change the columns ?