Rockbox currently has 2 different list implementations, the "classic" list (app/gui/bitmap/list.c) which is drawn directly using code, and skin list (apps/gui/bitmap/skinned-list.c) which uses the skin engine to draw everything.
The ultimate goal is to replace the classic implementation so only the skin engine one needs to exist. This cant happen until it can do everything the classic implementation can do:
Missing list features
- Filetree colors (need a tag to set the viewport foreground colour to the one the list should use)
- touch support - scrolling needs to be implemented in both directions (S.E list doesnt support it at all, classic supports up/down only)
- single/multi-line list items. current S.E doesnt deal with multi-line items very well (at all?). Probably need to add a tag to set the viewport to use when the list item is 1,2,etc lines (or figure out a way to make the one viewport work)
- list indenting
- Scroll all lines (though this looks terrible, it should probably be kept)
Missing skin engine features
- Backdrop viewport layer doesnt work in the list
- Need a way to specify the height of a viewport better than a pixel value (i.e font height + X)
- Maybe come up with a cleaner syntax to specify the list viewports (maybe remove it from the sbs)
Making it happen
Child viewports
A major problem with the current skinlist implementation is that it mangles the skin viewport and reimplements skin_render(), This is why the backdrop viewport doesnt work. To deal with this a potential fix is child viewports. Child viewports are simply an ID which can be resized and repositioned at runtime. (the actual implementation would get its own struct viewport so scrolling would work, but images would need to be drawn using the real viewport (I think!).)
These child viewports need the following tags:
- Ability to be pinned next to/above/below another child or the outer viewport edge
- Sized relative (% or pixels) to a child or outer viewport
- allowed to overlap (or told to not overlap)
All child viewports in a outer viewport are enabled or disabled together, and children ID's are only accessable from inside the same viewport.
An example for this would be
|[icon][spacing][text ][extra]|
where icon, spacing, text and extra are child vp's all glued to each other. icon would be pinned to the outer left edge with a set width, spacing would be pinned to icon with a runtime configured width (I.e list indent width, maybe 0), text is left pinned to spacing and right pinned to extra (where extra is a set width perhaps)...
Possible tags:
- vc(id) - child viewport create (with an id)
- vp(id, how, value) - cvp position. id in this case is the child to align to or - for outer viewport. 'how' might be "left, right, above, below, x-center, y-centre", value is how much (can be a percentage maybe?)
- vs(id, how, value) - cvp size. same as vp()
So, to do the example above:
%V(0,0,100,100,1) # outer viewport
%vc(icon) # create a child with id icon
%vs(icon, width, 10) # size to 10 pixels, (FIX THIS PART!)
%vp(-, left, 0) # the outer viewport should be pinned to the left edge at a distance of 0
%xd(icon,%xx()) # the thing actually in the child viewport
%vc(spaceing)%vp(icon,left,0)
%vs(spaceing, width, %Li) # set the width to the value of %Li
%vc(text)%vp(spacing, left, 0) #new child, pinned to spacing child
%vs(-, width, -10) # 10px less than the vp edge
....
Obviously the vs and vp tags need more work to make sense and do everything it needs to.
New repeater tags
Now, to make the above work we need a few tags to let the skin renderer know to redraw a viewport (real viewport) multiple times. (Tags to be decided)
- %Vr(what, child_id, how) - what is being drawn (i.e playlist viewer in WPS, or list), child_id is the child viewport to use to size each pass, how is whether it should tile or not.
If this tag is in a viewport then some magic will happen in skin_render_viewport() to make it keep repeating untill the 'what' says we are done or the viewport runs out of room. This obviously need to be the first thing in the viewport or the rest of the tags wont necessarily make any sense.
The way the viewport needs to be laid out is:
- %V(...)
- setup the child viewport which is used for the size of each item
- add more child viewports sized/positioned to be inside the main child
- use the repeater tag with the main child viewport label, this will then position all children correctly. The order of the child viewport setup is important, because if the subchildren are setup first they will not be positioned correctly the next time the viewport is drawn (for the redraw)
The goal is to use the same tag for the playlist viewer (currently %Vp() ) and skin lists, the P.V has some issues in that it expects to use the %i* tags to get the right tracks metadata, but this will obviously break. So a new tag will have to be added for it which basically says "this viewport is going to repeat X times to show the playlist viewer, so initialise what you need to and start with X offset into the playlist). Yet to be determinied if this is needed for skin lists.
Skin list tags
Finally new tags will be needed to get the info from the list (or adapted from the current tags)
- Get the list title
- Get the line icon
- get the line text
- get the line text colour
- get the line length <- not related to skin lists but needed anyway
- Scrollbar tag
- row/col/item number being drawn
- is current item selected?
Other
Will probably need to put this all in a new skin file (so not in the sbs) because it will get too complicated, this means it needs to be made to work in the UI viewport or not (like the wps)
--
JonathanGordon - 18 Feb 2013
Copyright © by the contributing authors.