Theming MythNews

Warning: This is a tutorial on MythUI Theming. Before beginning this tutorial, spend some time reading MythUI Theme Development to familiarize yourself with the concepts involved.

Note: It is easy to feel overwhelmed by the amount of work in this tutorial. It's important to remember that most of the tutorial is spent defining all the widgets that you can use over and over again in almost every single screen in MythTV. Once you have completed these, you can theme most of the basic screens in myth by calling these defined widgets with a few lines of XML. Persevere, and it will pay off in the end!

Note: This tutorial can technically be completed without creating any graphics, but you will enjoy the fruits of your labor much more if you take the time to do so.

This basic tutorial will explain how to theme a MythUI plugin from start to finish, for the absolute beginner.

Part I: Required Widgets

Basic understanding of the following widgets is necessary. You don't need to understand everything, but you will need a basic knowledge of their purpose. Before continuing further, read the section on the MythUI Theme Development page on each of them.

Part II: The Tutorial

MythNews is a very simple plugin. It's easy to theme and covers most of the essential theming concepts. You may wish to have the News-ui.xml page open in a browser for your reference. Each plugin and component of MythTV has an XML theme file associated with it, and each of those files will be documented in the wiki. Each named attribute, the widget type, and a brief description of the item will be documented.

For your first foray into theming, you will probably want to start by editing an existing theme. Go to the MythTV share directory on your frontend (Usually /usr/share/mythtv/themes or /usr/local/share/mythtv/themes) and make a backup copy of MythCenter.

cp -rf "MythCenter" "MythCenter-backup"

Editing the base.xml file

Now we have a copy of the theme directory for safety, and we can begin editing the original. Enter the MythCenter directory and edit the base.xml file with an editor of your choice. The base.xml is like an "include" file for the rest of your theme. You can save yourself tons of time by defining widgets, fonts, and windows in the base.xml file and then insert them later with a few lines of XML.

We're going to create all the widgets listed above to use later.

The Textarea Widget

We're not actually going to create a textarea in the base.xml , but we are going to define a font that we can use later in a textarea. Scroll to the bottom of the base.xml file, and just before the end of the theme file (</mythuitheme>) let's add the following text:

There are lots of attributes you can add to your text, and they are all thoroughly discussed on the MythUI Theme Development page, but these are the absolute basics. We defined a font name (newsfont), a font face (DejaVu Sans), a size (11), and a color in hexadecimal notation (#ffffff is white). Now, when we create a textarea later, we'll be able to do something like this (Note: this is an example, don't put this in your base.xml):

<textarea name="sometextarea">
<font>newsfont</font>
<value>I am some text, using the style you defined!</value>
</textarea>

The Textedit Widget

For the settings screens in MythNews, we're also going to need to define a text edit box. Before we start on the code, go to your graphics editing program and create the following images:

Required Images

In your preferred graphics package (Photoshop, The GIMP, etc.) create each of these files. You can design them however you like, just do your best to make them represent the states. Make sure to copy or save the files into the theme directory.

textedit_background.png (An unselected text edit box, 287x28)

textedit_background_selected.png (A selected text edit box, 287x28)

textedit_background_grey.png (A greyed out text edit box, 287x28)

cursor.png (A text cursor, 5x22)

Breaking Down the TextEdit

After your font definition from above, but before the </mythuitheme>, let's add the following text:

The textedit may look complicated, but it's actually pretty simple. Let's break it down line by line:

<textedit name="newstextedit">

We create a textedit widget called "newstextedit."

<area>0,0,287,28</area>

We specify an area. The format is x,y,width,height. The x and y coordinates are measured from the top left corner of the screen, but we'll set these to 0 because we're not actually placing it on screen at the moment, just defining it for use later. Later, when we use a textedit and have it inherit from this textedit, we can override any or all attributes by specifying them there. Our default textedit is going to be 287 pixels wide and 28 pixels tall.

<statetype name="background">

A statetype is a special type of widget that we use in other widgets. A statetype is basically a widget that behaves differently according to conditions. For example, we want our textarea to look different when it's selected, unselected, or greyed out. The statetype name for the background in a textedit is hardcoded as "background." For your textedit to work properly, the statetype (and subsequent states) must be named exactly like this. Now let's define the

Statetypes contain states. Active, Selected, and Inactive are hardcoded state names used in a textarea. We need all three states in our "background" statetype for our textarea to work. They represent the active but not in use, active and in use, and greyed out states, respectively. In each state we're going to add an imagetype widget. We are basically using a different image of our text area for each state, which myth will display based on which condition the textedit is in.

Of course, our textedit needs a space for the text to go. In this case, it needs to be called "text." Because the textarea is being created within another widget, you will see that the area is relative to the top left of the widget. We're going to place the text area just slightly down and to the right from that corner, and it will be slightly smaller width and heightwise. We're also doing to need to set a font. Look, it's the font we created above, newsfont! This is the first example we see of inheritance in action. Rather than defining the whole font again, we just call the font name, which inherits all those attributes.

</textedit>

Finally, we close our textedit widget.

The Button Widget

Required Images

buttonbackground.png (An unselected button, 150x35)

buttonbackground_selected.png (A selected button, 150x35)

buttonbackground_pushed.png (A pushed button, 150x35)

Breaking Down the Button

The button widget is a very simple widget. Let's add the following widget after our textarea from above:

Here is our first state, "Active." Active is an available (but not selected) button. We're going to add an image of an unselected button (buttonbackground.png) that is 150x35 pixels, and a text area inside that button. Here we use the <align> tag to center the text within the button, and our "newsfont" font.

Our second state is "selected." In this case, we've decided to be lazy. We want to use the exact same textarea, we just want the background image to be different. so we added from="active" to inherit everything from the active state, and just redefined the imagetype.

<state name="disabled" from="active" />

Here again we've chosen to inherit the whole disabled state from the active state.

The above may look a little daunting, but the buttonlist is just a couple of special tags that establish the behavior of the button list, and four statetypes. Since you've already created a statetype and understand what they do, let's break this widget definition down by chunks.

<area> - The default size of the button list (bearing in mind that we can override this later) is 349 pixels wide by 250 pixels tall.

<layout> - defines the list as a vertical buttonlist (we could also use horizontal or grid, but for this button list, we will do something traditional).

<spacing> - establishes the number of pixels which should be left between each button item.

<scrollstyle> - is a tag which sets how the scrolling of the list behaves-- "free" allows the selector to move freely through the list. If we used "center," the selected item would remain in the center and the list would float around it.

<wrapstyle> - establishes what happens when you get to the end of the list. We chose "items" because we want the last item in the list to wrap back to the first (other options are selection and none).

<buttonarea> - Sets the amount of the overall widget space to be devoted to the buttons. Here you'll see the first example of using percentages instead of pixels. This will maintain a consistent layout without having to change this pixel for pixel each time we use the widget at a different size.

In active, we create the buttonbackground imagetype (for a button that is unselected but available). The filename is widebuttonbackground.png.

We add a textarea widget for the text of our buttons. The area is set to use 85% of the width, and 30 pixels tall. The <cutdown> tag will truncate the text with ellipsis (...) if necessary. <align> sets the text to be centered within the button.

The buttonlist needs a sub-statetype called "buttoncheck." Buttoncheck contains three states, off, half, and full. These are checkboxes that indicate whether a selection at a lower level is unselected, partially selected, or fully selected. One example of this is the playlist selection lists in MythMusic.

We add the required "buttonarrow" imagetype to the button. This image will appear to indicate the button has a submenu. It appears conditionally (ie, only when needed).

We add the states "selected" and "inactive" and inherit everything but their backgrounds from "active."

This is more that we've seen before. Two more stateypes and we are done!

We create the "upscrollarrow" statetype. It contains two states, "off" and "full." Instead of creating different images this time, we're going to use the <alpha> tag to differentiate them from one another.

We create the "downscrollarrow" using an identical method as the upscrollarrow.

The checkbox is just two statetypes (background and checkstate), each containing three states.

Create the checkbox named "newscheckbox" with an area of 30x30.

Create a statetype called "background." This state defines the behavior of the background image.

Create three states in "background," active, selected, and disabled. Define an imagetype for each.

Create a statetype called "checkstate." This state defines the behavior of the check in the checkbox.

Create three states in "checkstate," off, half, and full. Define an imagetype for each.

Editing the news-ui.xml file

Once you have edited the base.xml file for MythCenter, you will need to restart your frontend (and/or switch to the MythCenter theme). The base.xml and menu-ui.xml files are read at frontend startup, but everything else can be changed on the fly.

After all of the effort above, we are finally ready to tackle the theming of MythNews! Most of the effort involved in this is already behind us. Now it is simply a matter of placing the widgets we've already defined on the screen in the places we wish.

MythTV will always attempt to load needed files from your theme's directory. If it fails to find them, however, it will fall back to files contained in the default (for 4:3 themes) and default-wide (for 16:9 themes) directories. If a wide theme is unable to find a file in default-wide, it will try default. Presently, most of the legacy themes do not have custom versions of the new MythUI screens, and are falling back to the default themes. This is true with MythNews as well. Because of this, the legacy themes do not contain the required news-ui.xml file. We will need to create a new one.

Now would be a good time to open the News-ui.xml wiki page as a reference. This will show us all of the windows and defined widget names we need to add to our theme file before it will work.

In the MythCenter directory, edit a new file called news-ui.xml. All MythUI Theme files begin and end with the <mythuitheme></mythuitheme> tags. Everything we do will be inside of these tags. So, add the following to the top of the file:

<mythuitheme>

The news window

Within the <mythuitheme> tags, individual screens in MythTV are defined in <window> tags. As we see on the News-ui.xml wiki page, we have three windows to create, news, editor, and config. Let's start with our first window, news. Add the following:

<window name="news">

Now we have two buttonlists, four textareas, and four imagetypes to add to this page to have all the required elements. We're going to use inheritance to make this a simple matter. Let's add our first required button list "siteslist."

That's it! We set the button list to start at coordinates 20x20, with dimensions of 200x300 (overriding the predefined version) and inherit everything else from the version in base.xml! The coordinates are set in the themeinfo.xml file, which sets the resolution of the overall theme. For MythCenter, that resolution is 800x600. All of our placement coordinates will be in a "field" of 800 pixels wide by 600 pixels tall. For more information on the themeinfo.xml file, see the section on it in MythUI Theme Development. That was so simple, let's add our other required buttonlist, articleslist.

You may be wondering why some imagetypes don't have a <filename> attribute. With all text and images in Myth, behaviors can differ slightly. If the widget is a required, named item, it is either filled by myth dynamically or turned on and off conditionally. In the case of the thumbnail above, it is always filled by the thumbnail from the RSS feed, so it's okay for it not to have a filename. In the case of the ispodcast imagetype, it is turned on and off conditionally, based on whether the article is a podcast. When images are dynamically filled, you can also set a "fallback" filename if there is none filled by mythtv.

Finally, let's close this window with:

</window>

The editor window

Using only the News-ui.xml page, can you add this window yourself? Try, then compare your results to those below!

How close did you come? If you did something wrong, reread this page and the MythUI Theme Development page to see what you didn't understand.

The config window

This exercise is entirely up to you. Using the News-ui.xml page, attempt to complete this window yourself. If you get stuck, you can check the news-ui.xml file download link at the bottom of the page to download the master version of the file to compare against.

Closing the MythUI File

Since we now have all of our windows defined, and all of the required UI elements added, we can close the file by adding:

</mythuitheme>

Save the file in your MythCenter directory, restart the frontend, and enter MythNews. If everything has gone according to plan, you should now be able to see all of your widgets in action!

What to do if something went wrong

If the plugin doesn't load, or if you don't see your widgets as you expected, the first place to check is the frontend log (or run mythfrontend from the console and read the console output). Most commonly, the problem is typographical errors in your XML. Mythfrontend helpfully tells you when there is a problem with your XML, and tells you the line and column in your file to check. If you can't figure out what's gone wrong, subscribe to the MythUI Theming list and ask your question there. Be prepared to quote your XML and your frontend log.

Finishing up

After completing this tutorial, you should have a solid understanding of how defining a widget, inheritance, and layout in MythUI work. Now go back and re-read the MythUI Theme Development page. You can start defining all the rest of the widgets as you wish, and using the links at the bottom of that page you can start theming the other screens and plugins in MythTV.

The logical next theming step is MythMovies, Which is nearly identical to MythNews, but adds one more widget, the buttontree. Taking the work you have started here, you would define the buttontree (as explained on MythUI Theme Development) and theme the screen in the movies-ui.xml file exactly as you did in the last part of this tutorial.

You may also want to look at the Terra source code for a great example of a MythUI theme in action.

Extra Credit Exercises

For extra credit/practice, do the following:

Keeping in mind that images, text, buttons, etc. in MythUI are drawn in the order in which they are defined, add a background image to the MythNews screen.

Read the Theme Development section on imagetypes. Make the alpha (transparency) values of your selected button pulse between 150 and 255. (Remember you need to reload the frontend when you change base.xml or menu-ui.xml).

Define a second font called "newsfontgrey". Make the font size 10 (slightly smaller than our existing font) and make the color grey (You can use the color palette here to determine the right color code to use). Now make all unselected buttons in MythNews use this font.

Cheater's Reference

For your reference (or cheating), see these completed versions of the XML referenced above: