Trying to implement a sort of utilities subroutine which can be called from other components. I tried to create an independent xml/brs pair with the basename "PeopleItem" but this didn't seem to work. I finally included a "<script ... PeopleItem.brs />" line in the xml file for the calling program. But I cannot get the content I'm trying to insert appear. So now, here is what I have:
This is the function I call:
' insert all in the People node into the People row ' Parameters: ' @crew - the People node returned from server ' @rowGrp - The 'PeopleRow' into which the people are to be inserted function CreatePeopleList(crew as object, rowGrp as object) as object pplRow =  cc = 0 for each person in crew poster = CreateObject("roSGNode", "Poster") poster.id = "person" + mid(stri(cc),2) cc = cc + 1 poster.height = 200 poster.width = 160 poster.failedBitmapUri = "pkg:/images/baseline_person_white_48dp.png"
' This is just a kludge for now. Will have to get uri from server if
' I can get it to work at all poster.uri = "pkg:/images/baseline_person_white_48dp.png" personName = CreateObject("roSGNode", "Label") personName = tr(person.Name) poster.appendChild(personName) rowGrp.appendChild("poster") end for end function
What I'm trying to accomplish here is to parse the People list and for each entry, create a "Poster" and populate it with the data from that entry, and perform an ".appendChild" onto the LayoutGroup. Should this not work?
Here is the calling function:
if (itemData.People <> invalid) and (itemData.People.count() > 0) setFieldText("peopleLabel", tr("Cast and Crew")) CreatePeopleList(itemData.People, m.top.findNode("peopleGroup")) end if
And here is the snippet from the component XML file that defines "peopleGroup":
<?xml version="1.0" encoding="utf-8" ?> <component name="MovieDetails" extends="JFGroup"> <children> <LayoutGroup id="main_group"> <LayoutGroup layoutDirection="vert" > <!-- Other stuff -->
<!-- "Cast and Crew" row --> <Label id="peopleLabel" /> <!-- This appears on the screen --> <! This is the LayoutGroup I'm trying to populate --> <LayoutGroup layoutDirection="horiz" itemSpacings="" id="peopleGroup"> </LayoutGroup>
<!-- The followong probably not relevant -->
</LayoutGroup> </LayoutGroup> </children> <interface> <field id="itemContent" type="node" onChange="itemContentChanged" /> <field id="selectedAudioStreamIndex" type="integer" /> </interface> <script type="text/brightscript" uri="pkg:/components/PeopleItem.brs" /> <script type="text/brightscript" uri="pkg:/source/utils/misc.brs" /> <script type="text/brightscript" uri="MovieDetails.brs" /> </component>
This is what I have so far. It would appear that what I'm trying to do makes sense but I don't know. This BrightScript programming seems to be quite different from anything I've encountered before.
I'm new to roku type programming and am having trouble with findNode finding a component. From what I can gather you should be able to declare a component and then discover it in another, but I am not able to do so. I have created the following:
<component name="PeopleItem" extends="Group"> <children> <LayoutGroup id="one_person" layoutDirection="vert" itemSpacings=""> <Poster id="personPoster" translation="[250,150]" width="300" height="450" horizAlign="center" font="font:SmallSystemFont" wrap="false" /> <Label id="personName" /> </LayoutGroup> </children> <interface> <function name="CreatePeopleList" /> </interface> <script type="text/brightscript" uri="PeopleItem.brs" /> </component>
sub init() ' Another failed attempt m.top.peopleItem = m.findNode("PeopleItem)") end sub function CreatePeopleList(crew as object) as object d = CreateObject("PeopleItem") pplRow =  for each person in crew if crew.PrimaryImageTag <> invalid d.personPoster = crew.PrimaryImageTag else px = "pkg:/images/baseline_person_white_48dp.png" end if d.personName = tr(person.Name) pplRow.push(d) end for return pplRow end function
And here is a snippen from /components/movies/MovieData.brs
if (itemData.People <> invalid) and (itemData.People.count() > 0) setFieldText("peopleLabel", tr("Cast and Crew")) node = m.top.findNode("peopleItem")
' The debugger breaks on the following line with error code "Member function not found in BrightScript Component or interface." ' but the error is caused by the previous line, because
' "node" at this point is "invalid" so am I calling it wrong or what?
' I've also tried capitalizing the P in people aboce
peeps = node.CallFunc("CreatePeopleList", itemData.People) stop if (peeps <> invalid) and (peeps.count() > 0) pg = m.top.findNode("peopleGroup") for each p in peeps pg.appendChild(p) end for end if end if
I hope I've included all related information. I think I've included everything the debugger would show. I have tried adding a "<acript ..." reference in MovieDetails.xml file and when I did this, I had to remove the init() function in PeopleIgem.brs because MovieDetails.brs has one.
This is probably something elementary but I cannot resolve it. If anyone can point out what I'm doing wrong, or if it's not possible to do it this way, I'd appreciate it, but from what I've gathered, it's simply a matter of adding a "<program ..." reference in the accompanying xml file and you're supposed to be set to go.
It seems that the PeopleItem file(s) are not being parsed. I put a "stop" statement in the init() for PeopleItem.brs and this was never reached. I did the same for the MovieDetails.brs file and it did reach this point.
It seems I just needed to do more research, although I had spent quite a bit of time doing so. Basically, what I had whei I originally posted was:
components/PeopleList.xml -> components/PeopleList.brs
components/movies/MovieDetails.xml -> components/movies/MovieDetails.brs
I had to add a <script... pkg:/components/PeopleList.brs to MovieDetails.xml which effectively made "PeopleList.brs" part of the "MovieDetails.brs", and then I simply call the function in PeopleList.brs as if it were in the MovieDetails.brs. When I did this, I had to remove the init() function from "PeopleList.brs" to avoid a warning about more than one init() function.
This solve the one problem, but I'm still not able to acomplish what I want. Will start new thread with my updated setup
Thank you for the response but I believe my problem stems from my lack of understanding of how this all works. I sort of got it to work, but now have found I'm going at it in the wrong direction. I don't have anything appropriate to submit, and again, I believe it's all my error. I'm trying to begin contributing to an existing project and attempting to make modifications on the code. Are the type questions I'm asking appropriate for this forum or is there a forum more dedicated to getting help? Right now I'm really struggling with how scoping works in all thls. I am now having this problem. I have a component like such:
<?xml version="1.0" encoding="utf-8" ?> <component name="PeopleItem" extends="JFGroup"> <interface> </interface> <script type="text/brightscript"> <![CDATA[ function init() as void m.personImage = m.top.findNode("personImage") m.personName = m.top.findNode("personName") end function ]]> ... more
and here's the JFGroup definition
<?xml version="1.0" encoding="utf-8" ?> <component name="JFGroup" extends="Group">
<interface> <field id="backPressed" type="boolean" alwaysNotify="true" /> <field id="lastFocus" type="node" /> <field id="overhangTitle" type="string" /> <field id="optionsAvailable" value="true" type="boolean" /> </interface> <script type="text/brightscript" uri="JFGroup.brs" /> </component>
I have a JFRowList component that contains:
<component name="JFRowList" extends="RowList"> <interface> <field id="backPressed" type="boolean" alwaysNotify="true" /> <field id="lastFocus" type="node" /> <field id="overhangTitle" type="string" /> <field id="optionsAvailable" value="true" type="boolean" /> </interface> ...
and in my "MovieDetails.xml" this child:
<JFRowList id="peopleGrid" itemSize="[200,200]" numRows="1" itemSpacing="[20, 20]" itemComponentName="PeopleItem" />
A line in my "MovieDetails.brs line 5 says:
m.top.optionsAvailable = false
Now, when the program is run, I get this error apparently each time an element is added to the JFRowList:
Warning occurred while setting a field of an RoSGNode -- Tried to set nonexistent field "optionsavailable" of a "PeopleItem" node at line 5 of file pkg:/components/movies/MovieDetails.brs
Why is this? It would appear, and I believe I saw in the documentation, that if you extend a custom interface, the new interface inherits all its (custom) parent's properties. What am I doing wrong?
Sorry for taking your time like this, but I would really love to get the hang of this.
One other thing I noticed, and didn't fully anticipate. Due to the fact that the error occurred so many times - I didn't count but expect that there was one for each child element in the row list, any child of the parent goes through the parent's init() function every time one of the children is created.
EDIT: This app uses a Makefile to build and install. It creates an "out" directory containing the files to include in the zip.. I eliminated this error by deleting the directory and rebuilding completely. Apparently it was not rewriting something that should have been updated, making the system still think it was a Group instead of a "JFGroup"