»
S
I
D
E
B
A
R
«
Building Your First App: The List Container
7 November 2009 by Rob Spectre
This entry is part 6 of 9 in the series Building Your First App

Last time, we finished up the last of the graphics work for our first application. The next step is building the list container. The list container is the primary interface of the application – the control that users browse through to view the content you’re delivering. The good news is they are not very hard to make and they are probably the most complex piece of your whole app.

This one is a little long-winded, I’ll warn you. But not at all as daunting as it might initially seem.

First we start much the same way that we did when building an image control – by setting its position and dimensions:

1
2
3
4
5
6
<control type="list" id="100">
   <posx>65</posx>
   <posy>235</posy>
   <width>492</width>
   <height>406</height>
</control>

Notice that we set the positioning five pixels to the right of the list.png image control and five pixels down. This will make the list seem indented with list.png as its background. Similarly, we reduced the dimensions both height and width by ten pixels, thus giving us a five pixel margin around our list container. We also assign it the id “100″ – the same value as our the defaultcontrol element we defined earlier.

Next, we define our orientation.

1
2
3
4
5
6
7
<control type="list" id="100">
   <posx>60</posx>
   <posy>230</posy>
   <width>502</width>
   <height>416</height>
   <orientation>vertical</orientation>
</control>

This element can have two values – horizontal or vertical. For this particular app, we want a vertical orientation (much like Auto-Tune The News). A horizontal orientation is generally used in panel containers, like those seen in Digg or Revision3.

Third, we need to define our item layout. This is the only part that gets a little tricky. Every item in your RSS feed gets parsed by Boxee and becomes a “ListItem.” The list container we are building will be populated by these ListItems and their appearance must be defined within this control. Consider the following XML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<control type="list" id="100">
   <posx>60</posx>
   <posy>230</posy>
   <width>502</width>
   <height>416</height>
   <orientation>vertical</orientation>
   <itemlayout width="502" height="65">
    <control type="label">
        <posx>0</posx>
        <posy>0</posy>
        <width>502</width>
        <height>62</height>
        <font>font40</font>
        <align>left</align>
        <aligny>center</aligny>
        <label>$INFO[ListItem.Label]</label>
        <textcolor>white</textcolor>
    </control>
    </itemlayout>
</control>

The item layout element – like the list control – is a container for all the subelements within it. In this case, we only have one, the ListItem’s Label (read: title). In it you will notice the same position and dimension elements (e.g. posx, width, etc). You will also notice the width and height attributes for the element.

What the item layout attributes do is define the total size of the individual item. In this case, we want to make it as wide as the list container and big enough to have some space between the text. We can then define the dimensions of our label control as slightly shorter, giving us a 3 pixel gap between the labels.

The next step after we define our item layout, is to define our focused item layout. If the item layout defines what all ListItems look like in our app, focused item layout defines how the one focused item in the list should look. This is how we distinguish to the user which piece of content they have selected.

This can be done many ways and fortunately Boxee has some built in features you can use without adding any more graphics assets. Take a look at this addition to our list container:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<control type="list" id="100">
   <posx>60</posx>
   <posy>230</posy>
   <width>502</width>
   <height>416</height>
   <orientation>vertical</orientation>
   <itemlayout width="502" height="65">
    <control type="label">
        <posx>0</posx>
        <posy>0</posy>
        <width>502</width>
        <height>62</height>
        <font>font40</font>
        <align>left</align>
        <aligny>center</aligny>
        <label>$INFO[ListItem.Label]</label>
        <textcolor>white</textcolor>
    </control>
    </itemlayout>
    <focusedlayout width="502" height="65">
      <control type="image">
           <posx>0</posx>
           <posy>0</posy>
           <width>502</width>
           <height>65</height>
           <texture>white.png</texture>
           <colordiffuse>DD171717</colordiffuse>
       </control>
       <control type="label">
           <visible>!Control.HasFocus(100)</visible>
           <posx>0</posx>
           <posy>0</posy>
           <width>502</width>
           <height>62</height>
           <font>font40</font>
           <align>left</align>
           <aligny>center</aligny>
           <label>$INFO[ListItem.Label]</label>
           <textcolor>white</textcolor>
           <selectedcolor>DD171717</selectedcolor>
       </control>
       <control type="label">
           <visible>Control.HasFocus(100)</visible>
           <posx>0</posx>
           <posy>0</posy>
           <width>502</width>
           <height>62</height>
           <font>font40</font>
           <align>left</align>
           <aligny>center</aligny>
           <label>$INFO[ListItem.Label]</label>
           <textcolor>white</textcolor>
           <selectedcolor>DD171717</selectedcolor>
           <scroll>true</scroll>
           <scrollspeed>30</scrollspeed>
       </control>
    </focusedlayout>
</control>

You’ll notice looks exactly like , only with a few additions. The first addition you will notice is the image control. What this does is give the selected item in the list a tinted background. To accomplish the tint look, we use a default image texture white.png and a colordiffuse element. The colordiffuse element will tint that white with the color you specify, making it in this case just a little more gray. The second difference you’ll notice is that there are two label controls instead of one.

We need two labels in the focused layout to handle two use cases – when the application has focus and when it does not. When Boxee is in focus and the user is actively browsing the list container, he/she sees the label control on the bottom. That label control is set to scroll the text of the label (if it is longer than the width allowed), letting the user preview the content’s full label before selecting it. But, what if that user clicks away into another application or a menu? Obviously we wouldn’t want to continue scrolling, which is what the label control above it does. It stops the scrolling and waits for the user to return his/her focus to the app before scrolling again.

Phew! This is getting long, but we’re almost there.

The final element in your list container is the plumbing to hook your RSS feed up to the application. It can be added easily, like below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<control type="list" id="100">
   <posx>60</posx>
   <posy>230</posy>
   <width>502</width>
   <height>416</height>
   <orientation>vertical</orientation>
   <itemlayout width="502" height="65">
    <control type="label">
        <posx>0</posx>
        <posy>0</posy>
        <width>502</width>
        <height>62</height>
        <font>font40</font>
        <align>left</align>
        <aligny>center</aligny>
        <label>$INFO[ListItem.Label]</label>
        <textcolor>white</textcolor>
    </control>
    </itemlayout>
    <focusedlayout width="502" height="65">
       <control type="image">
           <posx>0</posx>
           <posy>0</posy>
           <width>502</width>
           <height>65</height>
           <texture>white.png</texture>
           <colordiffuse>DD171717</colordiffuse>
       </control>
       <control type="label">
           <visible>!Control.HasFocus(100)</visible>
           <posx>0</posx>
           <posy>0</posy>
           <width>502</width>
           <height>62</height>
           <font>font40</font>
           <align>left</align>
           <aligny>center</aligny>
           <label>$INFO[ListItem.Label]</label>
           <textcolor>white</textcolor>
           <selectedcolor>DD171717</selectedcolor>
       </control>
       <control type="label">
           <visible>Control.HasFocus(100)</visible>   
           <posx>0</posx>
           <posy>0</posy>
           <width>502</width>
           <height>62</height>
           <font>font40</font>
           <align>left</align>
           <aligny>center</aligny>
           <label>$INFO[ListItem.Label]</label>
           <textcolor>white</textcolor>
           <selectedcolor>DD171717</selectedcolor>
           <scroll>true</scroll>
           <scrollspeed>30</scrollspeed>
       </control>
    </focusedlayout>
    <content type="url" url="rss://yourdomain.com/yourfeed.rss">
    </content>
</control>

It’s the easy piece of the whole list container puzzle – just plug in the path for your RSS feed into the url attribute, and you’re done-diggy. Once you drop your completed code in the group control after the metadata box image, you can reload the app and see your content now populating. Once you add the container to your app, your main.xml should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?xml version="1.0"?>
   <window type="window" id="14000">
   <defaultcontrol always="true">100</defaultcontrol>
   <allowoverlay>no</allowoverlay>
   <controls>
      <control type="group">
          <control type="image">
             <posx>0</posx>
             <posy>0</posy>
             <width>1280</width>
             <height>720</height>
             <texture>bg.png</texture>
          </control>
          <control type="image">
             <posx>60</posx>
             <posy>230</posy>
             <width>502</width>
             <height>416</height>
             <texture>list.png</texture>
         </control>
         <control type="image">
             <posx>630</posx>
             <posy>255</posy>
             <width>574</width>
             <height>355</height>
             <texture>details.png</texture>
          </control>
          <control type="list" id="100">
	   <posx>60</posx>
	   <posy>230</posy>
	   <width>502</width>
	   <height>416</height>
	   <orientation>vertical</orientation>
	   <itemlayout width="502" height="65">
	    <control type="label">
		<posx>0</posx>
		<posy>0</posy>
		<width>502</width>
		<height>62</height>
		<font>font40</font>
		<align>left</align>
		<aligny>center</aligny>
		<label>$INFO[ListItem.Label]</label>
		<textcolor>white</textcolor>
	    </control>
	    </itemlayout>
	    <focusedlayout width="502" height="65">
	       <control type="image">
		   <posx>0</posx>
		   <posy>0</posy>
		   <width>502</width>
		   <height>65</height>
		   <texture>white.png</texture>
		   <colordiffuse>DD171717</colordiffuse>
	       </control>
	       <control type="label">
		   <visible>!Control.HasFocus(100)</visible>
		   <posx>0</posx>
		   <posy>0</posy>
		   <width>502</width>
		   <height>62</height>
		   <font>font40</font>
		   <align>left</align>
		   <aligny>center</aligny>
		   <label>$INFO[ListItem.Label]</label>
		   <textcolor>white</textcolor>
		   <selectedcolor>DD171717</selectedcolor>
	       </control>
	       <control type="label">
		   <visible>Control.HasFocus(100)</visible>   
		   <posx>0</posx>
		   <posy>0</posy>
		   <width>502</width>
		   <height>62</height>
		   <font>font40</font>
		   <align>left</align>
		   <aligny>center</aligny>
		   <label>$INFO[ListItem.Label]</label>
		   <textcolor>white</textcolor>
		   <selectedcolor>DD171717</selectedcolor>
		   <scroll>true</scroll>
		   <scrollspeed>30</scrollspeed>
	       </control>
	    </focusedlayout>
	    <content type="url" url="rss://yourdomain.com/yourfeed.rss">
	    </content>
	</control>
      </control>
   </controls>
</window>

For more information of the possibilities of the list container, check out Boxee’s developer documentation.

Building In-Window Navigation
21 August 2009 by Rob Spectre

This week I had a client with a navigation requirement that can be frustrating for a lot of Boxee developers.  The application was for KidMango, an online video service chockful with excellent high quality children’s content like Care Bears, Where in the World is Carmen Sandiego? and Dennis the Menace.  Their service categorizes their extensive library in four age groups, so a natural requirement of their Boxee app to provide users with the ability of using those groups as navigation options.

Kid-friendly navigation ftw!

Kid-friendly navigation ftw!

One option would be to create entirely different windows for each age group for four xml files total.  But this is not 1994 and we’re not using FrontPage; this option is entirely too unwieldy to maintain.  We could leverage the API and use SetContentURL in an onclick event for each button, but some of these age groups have as many as 50 series in their RSS feeds.  Navigating on Boxee systems with poor hardware would lead to a very jerky experience; we definitely need a loading dialog.

So, for this unique use case I came up with this approach for In-Window navigation.  It satisfies our need to keep our code maintainable, while providing a strong experience for all hardware profiles.  Consider the following code attached to a button control:

<onclick lang="python"><![CDATA[
import mc
params = mc.Parameters()
params['title'] = "KidMango Kids"
params['link'] = "rss://apps.gonzee.tv/kidmango/series.php?channel=kids&pages=3"
mc.GetApp().ActivateWindow(14000, params)
]]></onclick>

Obviously assuming we’ve loaded the mc library already, what we’re doing here is giving each button two parameters – a title and a feed.  We then reactivate the existing window to trigger the Progress Dialog and load our container with the new feed.  Now we need to set up our list container to accept the data we send it:

<content type="url" url="App.Param(link)">

This method looks for the link parameter to connect the list container with a feed.  But, with this approach, it means that the initial state of the app will be blank – no good for sure.  We can solve this by attaching an onload event to the window that queues up the list container with the default feed:

<onload lang="python"><![CDATA[
import mc
params = mc.GetApp().GetLaunchedWindowParameters()
if (len(params) == 0):
mc.GetWindow(14000).GetList(111).SetContentURL("rss://apps.gonzee.tv/kidmango/series.php?channel=home&pages=5")
]]></onload>

And viola!  Junk hardware friendly in-window navigation. For this tip in action, install the KidMango app available soon in the App Box.

»  Substance: WordPress   »  Style: Ahren Ahimsa
© 2009, all rights reserved.