Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 69 Next »

Finally, let's put all the examples we've seen previously in the tutorial together, to create a typical Scene Graph application. As with every application, this application has a purpose. And the purpose of this application is to present all the various node classes and design/development principles for Roku Scene Graph, to let you quickly select node classes and design ideas for your application.

Example Application:

Tutorial Application Overview

Looking at, you'll note that the package components directory consists of the following directories and XML component files:


XML Component Files

  • tutorialpanelsetscene.xml
    The scene component for the application, extended from the OverhangPanelSetScene node class
  • contentreader.xml
    A generic Task node for reading Content Meta-Data for application content items from server XML files
  • categorieslistpanel.xml
    A medium-size ListPanel node that lists the example categories
  • categoryinfopanel.xml
    A medium-size Panel node that provides a description of each example category focused in the categories list panel
  • examplesgridpanel.xml
    A full-size GridPanel node that provides a grid of example posters for user selection of each example 

Note that if you've gone through the Scene Graph XML Tutorial from beginning to here, there is very little contained in that you haven't seen before. What this application does is pull together all the various Scene Graph nodes, components, designs, and development principles into a single application. So to complete the tutorial, we only need to describe certain aspects of the scene component file, tutorialpanelsetscene.xml, and how it pulls together the entire application, along with the associated server XML files.

Tutorial Application Scene Component Description

Looking at tutorialpanelsetscene.xml, you'll see that there is no <children> element XML markup to define Scene Graph nodes and components. Rather, tutorialpanelsetscene.xml is used only to create, manipulate, and remove components in the application scene graph, which are defined in the all the other XML component files in the application components directory.

Initial Content Meta-Data Reading

In fact, a large part of tutorialpanelsetscene.xml just creates and manipulates the same panel set described in OverhangPanelSetScene Markup. The big difference is not the panels or their sliding behavior, but in the greater amount of Content Meta-Data supplied by the server XML files supplied for the application, and allowing users to select a specific example item to view from the grids created by the examplesgridpanel.xml file containing the content meta-data for each item.

To start the application, the init() function runs a typical Task node content reader to get the initial content meta-data for the application:

m.readContentTask = createObject("roSGNode", "ContentReader")
m.readContentTask.observeField("content", "setcategories")
m.readContentTask.contenturi = ""
m.readContentTask.control = "RUN"

We're using the generic server XML file content reader Task node defined in contentreader.xml. If you have any questions about how this works, you could review Task Markup in this tutorial. In this case, once the ContentNode node containing the content meta-data is complete, it triggers the setcategories() callback function:

sub setcategories()
  m.categoriespanel ="CategoriesListPanel")
  m.categoriespanel.list.content = m.readContentTask.content

  m.categoryinfopanel ="CategoryInfoPanel")

  m.categoriespanel.list.observeField("itemFocused", "showcategoryinfo")
  m.categoryinfopanel.observeField("focusedChild", "slideexamplesgridpanel")

end sub

Dynamic Content Meta-Data Reading

The setcategories() callback function creates the categories list panel and category description panel defined in the categorieslistpanel.xml and categoryinfopanel.xml files, and adds them to the panel set. But importantly, when the ContentNode node created by the m.readContentTask object is assigned to the content field of the categories list panel object m.categoriespanel.list, the entire application is now set up to dynamically download additional content meta-data as needed by user actions.

To do this, we set up two field observers in the setcategories() function, one that observes the itemFocused field of the categories panel LabelList node, and the other to observe the focusedChild field of the category description panel. The first observer triggers a callback function that sends a category description to an <interface> field of the category description panel object m.categoryinfopanel, and creates an examples grid panel object to be populated with content meta-data dynamically by user focus on a category. The second controls the sliding of the panels in the panel set if the user selects a category, or presses the Right, Left, or Back remote control keys while focus is on a particular panel.

The key is that each item in the categoriescontent.xml server file contains another url content meta-data attribute that allows the rest of the application to dynamically load content meta-data from that URL:

  title = "Renderable Nodes" 
  description = "Basic Nodes That Show Things
  &#xA;  &#8226; Rectangle
  &#xA;  &#8226; Label
  &#xA;  &#8226; Poster" 
  shortdescriptionline1 = "Renderable Node Markup"
  url = "" />

So the title, description, and shortdescriptionline1 content meta-data attributes can all be used in the application when the user focuses or selects the item in the m.categoriespanel.list object, and the url attribute can be used to populate the examples grid panel with content meta-data downloaded from that URL. This is done when the showcategoryinfo() callback function is triggered by the user focusing on the category in the categories list panel list:

sub showcategoryinfo()
  categorycontent = m.categoriespanel.list.content.getChild(m.categoriespanel.list.itemFocused)

  m.categoryinfopanel.description = categorycontent.description

  m.examplespanel = createObject("roSGNode", "examplesGridPanel")

  m.examplespanel.overhangtext = categorycontent.shortdescriptionline1
  m.examplespanel.gridcontenturi = categorycontent.url
end sub

The function first extracts the content meta-data for the category item by accessing the child ContentNode node for the item, using the getChild() method with the itemFocused field value of the categories list panel list as the parameter. After that, the item content meta-data description attribute is assigned to the description <interface> element field of the categories description panel, causing that panel to display the description of the category. Then the examples grid panel object m.examplespanel is created, and the object overhangtext and gridcontenturi fields are assigned the values of the shortdescriptionline1 and url content meta-data attributes.

So the examples grid panel is being dynamically created and populated with content meta-data every time the user focuses on an item in the categories list panel list. Since the examples grid panel is configured to automatically download its content meta-data from its gridcontenturi <interface> element field, and configure the appearance of the panel based on the downloaded content meta-data, this download and configuration largely takes place before the user actually selects the category item. This automatic dynamic behavior makes the application feel quick and responsive to user actions; you can confirm this by actually using the application. 

Running New Components Based On User Selection

The goal of a video-on-demand application is to allow a user to select a video for playback. Roku Scene Graph provides a wide variety of UI elements to allow a user to proceed from starting the application to actually playing the video in a variety of different ways, with many different custom UI designs possible. Note that all of the lists and grids, widgets, other built-in node classes, and custom markup components you create, can be used in virtually unlimited combinations and variations to design a unique user interface for your VOD application.

At the point at which the user is ready to select a video (or for that matter, an audio file) for playback, you'll want to have a field observer set up to trigger the callback function that will actually perform the media playback. Generally this will be an observer on an itemSelected (or equivalent) field in a list or grid.

In our tutorial application, we set up this type of observer in the slideexamplesgridpanel() callback function. This function is triggered by a focus on the categories description panel, is designed to detect whether the user has moved the focus to the examples grid panel, and take the appropriate actions:

sub slideexamplesgridpanel()
  if not

    m.examplespanel.grid.observeField("itemSelected", "runselectedexample")


  end if 
end sub

The function first checks if the user is causing the panels in the panel set to slide to left or right. If the slide is towards the examples grid panel, the previously-created (and -configured) panel is added to the panel set using the appendChild() method. Then we set the observer on the itemSelected field of the examples grid panel grid, and move the focus to the panel. (If the user is causing the panels to slide the other way, towards the categories list panel, we set the focus on that panel.)

Now it's all up to the user (as always)... 

Replacing Old Screens With New Screens

The runselectedexample() callback function is largely the endpoint for this tutorial application. The application was designed to show the built-in node classes and design principles of Roku Scene Graph, and the runselectedexample() function replaces the example grid panel and panel set with a "screen" showing a Roku Scene Graph example in action, if a user selects an example grid item in the examples grid panel.

Remember how we used the url content meta-data attribute to configure the examples grid panel with dynamically-loaded content meta-data? This is the format of the content meta-data for each item in the examples grid panel from the server XML file:

  hdgridposterurl = 
  shortdescriptionline1 = "Rectangle Node" 
  shortdescriptionline2 = "RectangleExample" 
  x = "0" y = "0" />

Most of the content meta-data attributes are used to configure the PosterGrid node in the examples grid panel. But one, shortdescriptionline2, is used to supply the name of one of the dozens of component files defined in XML component files in the package components sub-directories. And with that name, we can create and add the example item as a "screen" to the application. Note these lines in the runselectedexample() function:

examplecontent = m.examplespanel.grid.content.getChild(m.examplespanel.grid.itemSelected)
example = examplecontent.shortdescriptionline2

First we access the specific item ContentNode node for the item using the getChild() method and the examples panel grid itemSelected field as the method parameter. Then we use string value of the attribute (the name of the component to run) to create the example component object, and append the component object to the panel set scene, while making the actual panel set itself invisible, and setting focus on the new component: = false = false

m.currentexample = createObject("roSGNode", example)


And the panel set "screen" is replaced with the m.currentexample object screen, which appears just like the example with the corresponding name seen throughout this entire tutorial.

Replacing New Screens With Old Screens

In some cases, the new "example" screens are essentially complete applications themselves, with their own content meta-data, and have their own user selection "endpoint" (such as the video list example, which is the same example described in Video List Markup, which can play several user-selected videos).



  • No labels