I have a MarkupGrid with a corresponding itemcomponent (MarkUpGridItem):
<MarkupGrid
id="lessons"
translation="[105,386]"
itemComponentName = "MarkupGridItem"
itemSize="[300,350]"
itemSpacing = "[40,20]"
numColumns = "5"
numRows = "2"
vertFocusAnimationStyle="fixedFocus"
/>
The grid item has a poster and also a second poster with a checkmark which remains invisible.
<component name = "MarkupGridItem" extends = "Group" >
<interface>
<field id = "itemContent" type = "node" onChange = "showcontent"/>
</interface>
<script type="text/brightscript" uri="MarkupGridItem.brs" />
<children>
<Poster
id="poster"
loadDisplayMode="scaleToFit"
width="300"
height="300"
loadWidth="300"
loadHeight="300"
translation="[0,0]" >
<Poster
id = "watched"
translation = "[ 250, 20 ]"
width = "30"
height = "30" />
</Poster>
</children>
</component>
The idea is that when the user clicks on a particular item, a video plays. When the video finishes we want the checkmark for the item the user clicked to become visible (based on a roArray to which the watched video id is added).
How can I target the particular item that was clicked in order to make changes just to that one.
I couldn't find a way so all I could do was reload the content of the markup grid. This managed to get the checkmark to appear but as soon as I used jumptoitem to move the focus to the watched item, the checkmark no longer appears.
In the past I've used a global assocarray as a lookup table to control elements on grid/row items (for progress, favourites, etc) and that worked - but it doesn't help to update an existing grid when something changes. You probably don't want to be observing something on global from every item.
It's weird that jumptoitem is hiding your 'watched' poster, probably worth focusing your efforts on figuring out why that's happening. Without seeing MarkupGridItem.brs I don't have a good answer but that's where I'd look.
Thanks @sanity-check for the suggestion.
Here is the code for the MarkUpItem.brs
sub init()
m.top.id = "markupgriditem"
m.itemposter = m.top.findNode("poster")
m.lessonNumber = m.top.findNode("lessonNumber")
m.watched = m.top.findNode("watched") 'the checkmark
end sub
sub showcontent()
? "ShowContent"
itemcontent = m.top.itemContent
m.itemposter.uri = itemcontent.url
m.lessonNumber.text = "Day " + itemcontent.shortdescriptionline1
watchedArray = m.top.getParent().getParent().watched 'watched field (array) in the screen node
if contains(watchedArray, (itemcontent.shortdescriptionline1).toInt())
m.watched.visible = true
m.watched.uri = "https://path/check_sequence.png"
else
m.watched.visible = false
end if
end sub
function contains(arr as Object, value as Integer) as Boolean
for each entry in arr
if entry = value
return true
end if
end for
return false
end function
This is the code that is running whenever returning from the video to the screen with the markupgrid
sub AddCheckmark(event as Object)
w = m.top.watched
w.push(m.top.track)
m.top.watched = w
m.lessonsList.content = m.lessonsContent 'this has the data for all items in grid
m.lessonsList.jumptoitem = m.lessonsList.itemFocused
end sub
The problem I have noticed is that if I don't add the last line, all items are rendered (The "Show COntent" message is printed for each item). But if I add the jumptoitem line, only a couple "Show Content" messages appear and then rendering stops and the rest of the list remains without updating. Thus, the checkmark doesn't appear.
Interesting! The getparent().getparent() thing works in grid item node. I've learned something at least.
I always feel like there's some tricky extra-threads stuff going on in the background with those, so it's possible things are happening in a different order to what we might expect.
What happens if you add some logging just before .jumptoitem ? Do "ShowContent" logs happen before, after, or a mix?
An alternative thing you can try, as your 'watched' list is in the same place as your content, is adding a .watched boolean field to your content nodes, and setting it to true for the relevant ones before reassigning .content=lessonsContent. Then your nodes are your single source of data for the grid, which I think is closer to how Roku intends these to work.
(Extend ContentNode, or use addField+setField)
In the end I managed to fin a way to do it. I used the itemHasFocus field:
<component name = "MarkupGridItem" extends = "Group" >
<interface>
<field id = "itemContent" type = "node" onChange = "showcontent"/>
<field id = "itemHasFocus" type = "float" onChange = "showfocus"/>
</interface>
sub showfocus(event as Object)
if event.getData() = 1
watchedArray = m.top.getParent().getParent().watched
if contains(watchedArray, m.number)
m.watched.visible = true
m.watched.uri = "https://path/check_sequence.png"
end if
end if
end sub
Works in my case because these are very short videos that don't move automatically from one video to the next, so the selected video is the one that has the focus upon returning from the video screen. The updating of the watched list happens before this runs.