HaviXlet
来源:百度文库 编辑:神马文学网 时间:2024/05/20 16:13:00
HaviExample.java 代码如下:/***********************************************************************************
*
* THIS SOFTWARE IS COPYRIGHT STEVEN MORRIS 2002. ALL RIGHTS RESERVED
*
* THIS SOFTWARE IS FREE FOR NON COMMERCIAL USE FOR THE PURPOSE OF LEARNING MHP. ANY
* USE FOR OTHER PURPOSES IS PROHIBITED UNLESS WRITTEN AGREEMENT IS OBTAINED.
*
* DISTRIBUTION OF THIS CODE IS PROHIBITED
*/
// Import the standard package that we need to be an Xlet
import javax.tv.xlet.*;// We need java.io to read data from files.
import java.io.*;// The classes related to graphics and the user interface are scattered across a
// lot of packages. MHP is built on several other standards, and each of these
// tried to fix the problems with AWT that they encountered. MHP adds some
// fixes of its own, resulting in a lot of different packages.
import java.awt.*;
import java.awt.event.*;
import org.havi.ui.*;
import org.havi.ui.event.*;
import org.dvb.ui.*;
/**
* This Xlet will be visible on-screen, so we extend org.havi.ui.HComponent
* (NOT java.awt.Component). it also implements java.awt.KeyListener to
* receive keypresses from an RCU.
*
* Since this is quite a complex Xlet that will be running for a long time,
* we do most of the work in a separate thread. For this reason, the Xlet
* implements the Runnable interface.
*/
public class HaviExample extends HComponent implements Xlet, Runnable, KeyListener { /**************************************************************************
*
* Standard Xlet lifecycle methods and constructors
*/
// A private field to hold a reference to our Xlet context
// A private variable to store our Xlet context. In this case, we do actually
// use this, showing why it's a good idea to keep a reference to the Xlet context.
private XletContext context; // A private variable that keeps a reference to the thread that
// will do all of the work.
private Thread myWorkerThread; /**
* A default constructor, included for completeness.
*/
public HaviExample()
{
}
/**
* Initialise the Xlet. Unlike some of the other Xlet examples, this actually does
* some real initialisation.
*/
public void initXlet(javax.tv.xlet.XletContext context) throws javax.tv.xlet.XletStateChangeException
{
// We keep a reference to our Xlet context because doing so is good practise
this.context = context; // load the image to be displayed in the graphics plane. This should maybe
// get done in startXlet() instead, depending on the size of the image and
// the time it takes to load. if this is being loaded from a DSM-CC
// carousel, it should definitely be loaded after startXlet() is called.
loadForegroundBitmap(); // Load the message that we will display
try {
// This is all standard java.io file reading, so we won't explain it.
// If you really need to know, look at a decent Java book.
BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream("message.txt"))); // Read the first line from the file. Our message will only be one
// line long, in this case.
message = in.readLine();
}catch(IOException e){
// Something went wrong reading the message file.
System.out.println("I/O exception reading message.txt");
}
}
/**
* Start the Xlet. This is where we actually start doing useful work.
*/
public void startXlet() throws javax.tv.xlet.XletStateChangeException
{
// startXlet() should not block for too long, and doing UI stuff is
// way too long. To solve this, we start another thread to do the
// work.
myWorkerThread = new Thread(this);
myWorkerThread.start();
} /**
* Pause the Xlet. This method cannot throw any exceptions, since an Xlet MUST
* pause itself when asked. However, exactly what the Xlet should do to pause
* itself is not specified. Doing nothing is allowed, but is not a good idea.
*/
public void pauseXlet()
{
// do what we need to in order to pause the Xlet.
doPause();
} /**
* Destroy the Xlet. This should release all resources, finish all threads and then exit.
* If the argument is false, then this method can refuse to be destroyed by throwing an
* XletStateChangeException.
*/
public void destroyXlet(boolean unconditional) throws javax.tv.xlet.XletStateChangeException
{
if (unconditional) {
// We have been ordered to terminate, so we obey the order politely and release any
// scarce resources that we are holding.
doDestroy();
}
else {
// We have had a polite request to die, so we can refuse this request if we want.
throw new XletStateChangeException("Please don't let me die!");
}
} /**************************************************************************
*
* The methods below this point are the ones which actually do all of the work
* related to putting something on the screen.
*/
// Before we can draw on the screen, we need an HScene to draw into. This
// variable will hold a reference to our HScene
private HScene scene; // The image that we will show
private Image image; // The message that will get printed. This is read from a file in initXlet()
private String message; // this holds the alpha (transparency) level that we will be using
private int alpha = 0;
// this object is responsible for displaying the background I-frame
private HaviBackgroundController backgroundManager;
/**
* The main method for the worker thread. This is where most of the work is done.
*/
public void run()
{
// We need quite a few resources before we can start doing anything.
getResources(); // This component should listen for AWT key events so that it can respond to them.
addKeyListener(this); // This adds the background image to the display. The background image is
// displayed in the background plane.
displayBackgroundImage(); // The bitmap image is shown in the graphics plane.
displayForegroundBitmap();
}
/**
* This function is responsible for getting the resources we need to execute and
* for setting up the main component for the Xlet.
*/
public void getResources() {
// Before we can do anything, we need to create a new HScene so that we
// can display something on the screen. First, we get a reference to
// the HSceneFactory...
HSceneFactory factory = HSceneFactory.getInstance(); // ...and then we can get an HScene.
// First, we create an HSceneTemplate
HSceneTemplate hst = new HSceneTemplate(); // Set it to cover the entire screen
hst.setPreference(
HSceneTemplate.SCENE_SCREEN_DIMENSION,
new org.havi.ui.HScreenDimension(1,1),
HSceneTemplate.REQUIRED);
hst.setPreference(
HSceneTemplate.SCENE_SCREEN_LOCATION,
new org.havi.ui.HScreenPoint(0,0),
HSceneTemplate.REQUIRED);
// Now actually get the HScene
scene = factory.getBestScene(hst);
// Since we didn't specify a size for our HScene when we created it,
// we need to find its size
Rectangle rect = scene.getBounds(); // Set the size of our component to fill the HScene, make it
// visible and set its background colour to be black.
setBounds(rect);
setVisible(true);
setBackground(Color.black); // Add ourselves to the HScene. While we're adding components to the
// scene, we should hide it to avoid any nasty flickering, but HScenes
// are not visible when they are created.
scene.add(this);
scene.setVisible(true); // Give focus to this component
this.requestFocus();
} /**
* This method is responsible for displaying the background image
* on the screen. This image will be displayed in the background
* plane, not the graphics plane. See the graphics tutorial for
* a discussion of the differences between the two planes and how
* they work together.
*/
public void displayBackgroundImage() {
// We've defined a separate object for displaying and managing
// the background image.
backgroundManager = new HaviBackgroundController(); // If we can initialise the background manager (which means we have got
// the resources we need to display the image), we load and display an
// image in the background plane.
if (backgroundManager.init()) {
backgroundManager.display("background.png");
}
} /**
* This method loads the bitmap that we will display in the component.
* The image can be loaded from a local filesystem or from a DSM-CC
* object carousel using the same code, with only the latency being
* different.
*
* This is fairly standard Java image loading, and so we won't
* examine this as closely as the rest of the example. A good Java
* book will tell you everything you need to know about this topic.
*/
public void loadForegroundBitmap() {
// Create a MediaTracker to tell us when the image has loaded
MediaTracker tracker = new MediaTracker(this);
// Then load the image
image = Toolkit.getDefaultToolkit().getImage("foreground.png"); // add the image to the MediaTracker...
tracker.addImage(image, 0); // ...and wait for it to finish loading
try{
tracker.waitForAll();
}
catch(InterruptedException e) {
// Ignore the exception, since there's not a lot we can do.
image = null;
} }
/**
* Display the foreground image in the AWT component
*/
public void displayForegroundBitmap()
{
} /**
* This method is used by pauseXlet() to do the tasks that should be carried out
* when the Xlet is paused. In this case, that means hiding the visible
* parts of the application and freeing up any resources we're using.
*/
public void doPause()
{
scene.setVisible(false);
// Dispose of the background image
backgroundManager.dispose();
}
/**
* This method is used by destroyXlet() to do the tasks that should be carried out
* when the Xlet is killed. In this case, that means disposing of AWT components
* and freeing the associated resources. Remember that some AWT elements must be
* freed explicitly in order for them to be disposed of completely. This avoids
* resource leaks.
*/
public void doDestroy()
{
// Hide ourself and remove any components from the HScene
scene.setVisible(false);
scene.remove(this); // Destroy the image buffer
image.flush();
image = null; // Dispose of the background image.
backgroundManager.dispose(); // Dispose of our HScene
HSceneFactory.getInstance().dispose(scene);
scene = null;
} /**
* This is a standard AWT paint method for repainting the contents of the
* component.
*/
public void paint(Graphics graphics) { // Get the size of this component so that we can clear it properly.
Dimension size = getSize(); /* Clear the background of the component to the current
transparency level. Since standard AWT doesn't support
transparency, we have to use an org.dvb.ui.DVBColor
object rather than a java.awt.Color
object */
graphics.setColor(new DVBColor(0,0,0,alpha));
graphics.fillRect(0,0,size.width,size.height);
// If the image has been loaded, add it to the component. This
// is necessary in some MHP applications because the long latency
// of the DSM-CC object carousel means that images may not have
// loaded by the time a component is added to the scene. Checking
// first allows you to avoid any graphics glitches caused by your
// application assuming it has data that hasn't finished loading
// yet.
if (image != null) {
// Draw the image from the buffer
graphics.drawImage(image, 100, 100, null);
} // Once we've drawn the image, we can draw the message on top of it. // Set the font to be the default MHP font.
graphics.setFont(new Font("Tiresias", Font.PLAIN, 36));
// Set the text colour
graphics.setColor(Color.white); // Drawing the string may cause an error to get thrown, so we
// surround it with a 'try' block.
try{
graphics.drawString(message,300,350);
}catch(Throwable t) {
// Catch any errors that get thrown.
t.printStackTrace();
}
}
/**************************************************************************
*
* Below here are the methods that implement the KeyListener interface
*/ /**
* keyPressed is the only key event that gets generated by the set-top box. We
* use this to listen for the keys that we care about.
*/
public void keyPressed(KeyEvent key) {
// What key has been pressed?
switch(key.getKeyCode()){
// if we have the 'up' key...
case KeyEvent.VK_UP: {
// increase the alpha level
alpha+=128;
if(alpha>255) alpha = 255;
//and repaint the screen.
repaint();
break;
}
case KeyEvent.VK_DOWN: {
// decrease the alpha level
alpha-=128;
if(alpha<0) alpha=0;
//and repaint the screen.
repaint();
break;
}
default: {
// do nothing
break;
}
}
}
public void keyTyped(KeyEvent key)
{
// Ignored
} public void keyReleased(KeyEvent key)
{
// Ignored
}
} HaviBackgroundController.java/***********************************************************************************
*
* THIS SOFTWARE IS COPYRIGHT STEVEN MORRIS 2002. ALL RIGHTS RESERVED
*
* THIS SOFTWARE IS FREE FOR NON COMMERCIAL USE FOR THE PURPOSE OF LEARNING MHP. ANY
* USE FOR OTHER PURPOSES IS PROHIBITED UNLESS WRITTEN AGREEMENT IS OBTAINED.
*
* DISTRIBUTION OF THIS CODE IS PROHIBITED
*/// Import the HAVi UI classes that we need for this
import org.havi.ui.HScreen;
import org.havi.ui.HBackgroundDevice;
import org.havi.ui.HBackgroundConfiguration;
import org.havi.ui.HBackgroundImage;
import org.havi.ui.HStillImageBackgroundConfiguration;
import org.havi.ui.HConfigurationException;
import org.havi.ui.HPermissionDeniedException;
import org.havi.ui.HBackgroundConfigTemplate;
// Since some of the graphics configuration requires scarce resources, we
// need to use the DAVIC resource notification API
import org.davic.resources.*;/**
* This class handles the display of background images in an easy-to
* use way. Setting this up can be quite complex, and so in the case
* we've relegated it to a separate class to make it a little easier to
* understand.
*/
class HaviBackgroundController implements org.davic.resources.ResourceClient{ // The background device that we will use for displaying the image
private HBackgroundDevice backdevice; // The configuration for that background device
private HStillImageBackgroundConfiguration backconfig;
/**
* This method will initialise the video and graphics devices to allow
* them to display the background image.
*/
public boolean init()
{
// We first need to get the background device that we will use for
// displaying the image. To do this, we need to first decide which
// HScreen we will use. In this case (and most others), we will use
// the default one.
HScreen screen = HScreen.getDefaultHScreen();
// Once we have that, we get the default background device for that HScreen
HBackgroundDevice backdevice = screen.getDefaultHBackgroundDevice(); // Once we have a reference to the device, we can get a configuration for it.
// Get a configuration that we can use
HBackgroundConfigTemplate backgroundConfigurationTemplate = new
HBackgroundConfigTemplate();
backgroundConfigurationTemplate.setPreference(
HBackgroundConfigTemplate.FLICKER_FILTERING,
HBackgroundConfigTemplate.REQUIRED); HBackgroundConfiguration backconfig;
backconfig = backdevice.getBestConfiguration(
backgroundConfigurationTemplate);
// Can we reserve the device so that we can change the settings on it?
if (backdevice.reserveDevice(this))
{
// If we can, we set the configuration of the background device to
// the one we got above - this is the default configuration for
// this device.
try
{
backdevice.setBackgroundConfiguration(backconfig);
}
catch (Exception ex)
{
System.out.println("Can't initialise the background device");
// Release the device so that other applications can use it, if necessary.
backdevice.releaseDevice();
return false;
} // We need to check if we can put an image in the background in
// this configuration, since we can't do this in every configuration.
if(backconfig instanceof HStillImageBackgroundConfiguration)
{
// We can use this
this.backconfig = (HStillImageBackgroundConfiguration)backconfig;
this.backdevice = backdevice;
return true;
}
else
{
// If we can't, we again release the device since it's
// no use to us.
backdevice.releaseDevice();
}
}
return false;
} /**
* Free the resources we needed to display background images.
* Some implementations leave the image there, but there is an explicit
* warning in the MHP specification that this may not happen on all
* implementations. If you want to be sure that your image is still
* visible, don't do this.
*/
public void dispose()
{
// Check if we have something to dispose of
if (backdevice != null)
{
// RZlease the device and clear any references
backdevice.releaseDevice();
backdevice = null;
backconfig = null;
}
}
/**
* Display a background image
*/
public void display(String filename)
{
// Check we have the resources we need to display a background image
if(backconfig != null) {
// Create a new background image. The image is loaded from the
// filename that we pass in.
HBackgroundImage backimage = new HBackgroundImage(filename); // Now display the image. This can throw several exceptions, so we
// enclose it in a 'try' block
try {
backconfig.displayImage(backimage);
}
catch (java.io.IOException ioe) {
// Ignore it, but print a message to tell the user what's happened.
System.out.println("Can't display background image - IO exception");
ioe.printStackTrace();
}
catch (HPermissionDeniedException hpde) {
// We don't have permission to displayan image. We just ignore it.
System.out.println("Can't display background image - permission denied");
}
catch (HConfigurationException hce) {
// We don't have permission to displayan image. We just ignore it.
System.out.println("Can't display background image - configuration exception");
hce.printStackTrace();
}
}
} /**************************************************************************
*
* These methods are inherited from the ResourceClient interface and are used
* to tell the application when it has lost access to its resources (or
* when it is about to lose access to them). This gives the application a
* chance to clean up when it loses access to a resource, and gives it a
* chance to handle things gracefully.
*/ /**
* This method gets called when the resource manager requests that we give
* up a resource. We can refuse to do so, and that's what we do in this
* case (even though we shouldn't).
*/
public boolean requestRelease(ResourceProxy proxy, Object requestData) {
return false;
} /**
* This method gets called when the resource manager informs us that we must
* release a resource
*/
public void release(ResourceProxy proxy) {
// release control of the background device
backdevice.releaseDevice();
} /**
* This method gets called when the resource manager tells us we've
* lost access to a resource and we should clean up after ourselves.
*/
public void notifyRelease(ResourceProxy proxy) {
// release control of the background device. Even though we don't
// have control of it, this makes sure everything is synchronized.
backdevice.releaseDevice();
}
}
*
* THIS SOFTWARE IS COPYRIGHT STEVEN MORRIS 2002. ALL RIGHTS RESERVED
*
* THIS SOFTWARE IS FREE FOR NON COMMERCIAL USE FOR THE PURPOSE OF LEARNING MHP. ANY
* USE FOR OTHER PURPOSES IS PROHIBITED UNLESS WRITTEN AGREEMENT IS OBTAINED.
*
* DISTRIBUTION OF THIS CODE IS PROHIBITED
*/
// Import the standard package that we need to be an Xlet
import javax.tv.xlet.*;// We need java.io to read data from files.
import java.io.*;// The classes related to graphics and the user interface are scattered across a
// lot of packages. MHP is built on several other standards, and each of these
// tried to fix the problems with AWT that they encountered. MHP adds some
// fixes of its own, resulting in a lot of different packages.
import java.awt.*;
import java.awt.event.*;
import org.havi.ui.*;
import org.havi.ui.event.*;
import org.dvb.ui.*;
/**
* This Xlet will be visible on-screen, so we extend org.havi.ui.HComponent
* (NOT java.awt.Component). it also implements java.awt.KeyListener to
* receive keypresses from an RCU.
*
* Since this is quite a complex Xlet that will be running for a long time,
* we do most of the work in a separate thread. For this reason, the Xlet
* implements the Runnable interface.
*/
public class HaviExample extends HComponent implements Xlet, Runnable, KeyListener { /**************************************************************************
*
* Standard Xlet lifecycle methods and constructors
*/
// A private field to hold a reference to our Xlet context
// A private variable to store our Xlet context. In this case, we do actually
// use this, showing why it's a good idea to keep a reference to the Xlet context.
private XletContext context; // A private variable that keeps a reference to the thread that
// will do all of the work.
private Thread myWorkerThread; /**
* A default constructor, included for completeness.
*/
public HaviExample()
{
}
/**
* Initialise the Xlet. Unlike some of the other Xlet examples, this actually does
* some real initialisation.
*/
public void initXlet(javax.tv.xlet.XletContext context) throws javax.tv.xlet.XletStateChangeException
{
// We keep a reference to our Xlet context because doing so is good practise
this.context = context; // load the image to be displayed in the graphics plane. This should maybe
// get done in startXlet() instead, depending on the size of the image and
// the time it takes to load. if this is being loaded from a DSM-CC
// carousel, it should definitely be loaded after startXlet() is called.
loadForegroundBitmap(); // Load the message that we will display
try {
// This is all standard java.io file reading, so we won't explain it.
// If you really need to know, look at a decent Java book.
BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream("message.txt"))); // Read the first line from the file. Our message will only be one
// line long, in this case.
message = in.readLine();
}catch(IOException e){
// Something went wrong reading the message file.
System.out.println("I/O exception reading message.txt");
}
}
/**
* Start the Xlet. This is where we actually start doing useful work.
*/
public void startXlet() throws javax.tv.xlet.XletStateChangeException
{
// startXlet() should not block for too long, and doing UI stuff is
// way too long. To solve this, we start another thread to do the
// work.
myWorkerThread = new Thread(this);
myWorkerThread.start();
} /**
* Pause the Xlet. This method cannot throw any exceptions, since an Xlet MUST
* pause itself when asked. However, exactly what the Xlet should do to pause
* itself is not specified. Doing nothing is allowed, but is not a good idea.
*/
public void pauseXlet()
{
// do what we need to in order to pause the Xlet.
doPause();
} /**
* Destroy the Xlet. This should release all resources, finish all threads and then exit.
* If the argument is false, then this method can refuse to be destroyed by throwing an
* XletStateChangeException.
*/
public void destroyXlet(boolean unconditional) throws javax.tv.xlet.XletStateChangeException
{
if (unconditional) {
// We have been ordered to terminate, so we obey the order politely and release any
// scarce resources that we are holding.
doDestroy();
}
else {
// We have had a polite request to die, so we can refuse this request if we want.
throw new XletStateChangeException("Please don't let me die!");
}
} /**************************************************************************
*
* The methods below this point are the ones which actually do all of the work
* related to putting something on the screen.
*/
// Before we can draw on the screen, we need an HScene to draw into. This
// variable will hold a reference to our HScene
private HScene scene; // The image that we will show
private Image image; // The message that will get printed. This is read from a file in initXlet()
private String message; // this holds the alpha (transparency) level that we will be using
private int alpha = 0;
// this object is responsible for displaying the background I-frame
private HaviBackgroundController backgroundManager;
/**
* The main method for the worker thread. This is where most of the work is done.
*/
public void run()
{
// We need quite a few resources before we can start doing anything.
getResources(); // This component should listen for AWT key events so that it can respond to them.
addKeyListener(this); // This adds the background image to the display. The background image is
// displayed in the background plane.
displayBackgroundImage(); // The bitmap image is shown in the graphics plane.
displayForegroundBitmap();
}
/**
* This function is responsible for getting the resources we need to execute and
* for setting up the main component for the Xlet.
*/
public void getResources() {
// Before we can do anything, we need to create a new HScene so that we
// can display something on the screen. First, we get a reference to
// the HSceneFactory...
HSceneFactory factory = HSceneFactory.getInstance(); // ...and then we can get an HScene.
// First, we create an HSceneTemplate
HSceneTemplate hst = new HSceneTemplate(); // Set it to cover the entire screen
hst.setPreference(
HSceneTemplate.SCENE_SCREEN_DIMENSION,
new org.havi.ui.HScreenDimension(1,1),
HSceneTemplate.REQUIRED);
hst.setPreference(
HSceneTemplate.SCENE_SCREEN_LOCATION,
new org.havi.ui.HScreenPoint(0,0),
HSceneTemplate.REQUIRED);
// Now actually get the HScene
scene = factory.getBestScene(hst);
// Since we didn't specify a size for our HScene when we created it,
// we need to find its size
Rectangle rect = scene.getBounds(); // Set the size of our component to fill the HScene, make it
// visible and set its background colour to be black.
setBounds(rect);
setVisible(true);
setBackground(Color.black); // Add ourselves to the HScene. While we're adding components to the
// scene, we should hide it to avoid any nasty flickering, but HScenes
// are not visible when they are created.
scene.add(this);
scene.setVisible(true); // Give focus to this component
this.requestFocus();
} /**
* This method is responsible for displaying the background image
* on the screen. This image will be displayed in the background
* plane, not the graphics plane. See the graphics tutorial for
* a discussion of the differences between the two planes and how
* they work together.
*/
public void displayBackgroundImage() {
// We've defined a separate object for displaying and managing
// the background image.
backgroundManager = new HaviBackgroundController(); // If we can initialise the background manager (which means we have got
// the resources we need to display the image), we load and display an
// image in the background plane.
if (backgroundManager.init()) {
backgroundManager.display("background.png");
}
} /**
* This method loads the bitmap that we will display in the component.
* The image can be loaded from a local filesystem or from a DSM-CC
* object carousel using the same code, with only the latency being
* different.
*
* This is fairly standard Java image loading, and so we won't
* examine this as closely as the rest of the example. A good Java
* book will tell you everything you need to know about this topic.
*/
public void loadForegroundBitmap() {
// Create a MediaTracker to tell us when the image has loaded
MediaTracker tracker = new MediaTracker(this);
// Then load the image
image = Toolkit.getDefaultToolkit().getImage("foreground.png"); // add the image to the MediaTracker...
tracker.addImage(image, 0); // ...and wait for it to finish loading
try{
tracker.waitForAll();
}
catch(InterruptedException e) {
// Ignore the exception, since there's not a lot we can do.
image = null;
} }
/**
* Display the foreground image in the AWT component
*/
public void displayForegroundBitmap()
{
} /**
* This method is used by pauseXlet() to do the tasks that should be carried out
* when the Xlet is paused. In this case, that means hiding the visible
* parts of the application and freeing up any resources we're using.
*/
public void doPause()
{
scene.setVisible(false);
// Dispose of the background image
backgroundManager.dispose();
}
/**
* This method is used by destroyXlet() to do the tasks that should be carried out
* when the Xlet is killed. In this case, that means disposing of AWT components
* and freeing the associated resources. Remember that some AWT elements must be
* freed explicitly in order for them to be disposed of completely. This avoids
* resource leaks.
*/
public void doDestroy()
{
// Hide ourself and remove any components from the HScene
scene.setVisible(false);
scene.remove(this); // Destroy the image buffer
image.flush();
image = null; // Dispose of the background image.
backgroundManager.dispose(); // Dispose of our HScene
HSceneFactory.getInstance().dispose(scene);
scene = null;
} /**
* This is a standard AWT paint method for repainting the contents of the
* component.
*/
public void paint(Graphics graphics) { // Get the size of this component so that we can clear it properly.
Dimension size = getSize(); /* Clear the background of the component to the current
transparency level. Since standard AWT doesn't support
transparency, we have to use an org.dvb.ui.DVBColor
object rather than a java.awt.Color
object */
graphics.setColor(new DVBColor(0,0,0,alpha));
graphics.fillRect(0,0,size.width,size.height);
// If the image has been loaded, add it to the component. This
// is necessary in some MHP applications because the long latency
// of the DSM-CC object carousel means that images may not have
// loaded by the time a component is added to the scene. Checking
// first allows you to avoid any graphics glitches caused by your
// application assuming it has data that hasn't finished loading
// yet.
if (image != null) {
// Draw the image from the buffer
graphics.drawImage(image, 100, 100, null);
} // Once we've drawn the image, we can draw the message on top of it. // Set the font to be the default MHP font.
graphics.setFont(new Font("Tiresias", Font.PLAIN, 36));
// Set the text colour
graphics.setColor(Color.white); // Drawing the string may cause an error to get thrown, so we
// surround it with a 'try' block.
try{
graphics.drawString(message,300,350);
}catch(Throwable t) {
// Catch any errors that get thrown.
t.printStackTrace();
}
}
/**************************************************************************
*
* Below here are the methods that implement the KeyListener interface
*/ /**
* keyPressed is the only key event that gets generated by the set-top box. We
* use this to listen for the keys that we care about.
*/
public void keyPressed(KeyEvent key) {
// What key has been pressed?
switch(key.getKeyCode()){
// if we have the 'up' key...
case KeyEvent.VK_UP: {
// increase the alpha level
alpha+=128;
if(alpha>255) alpha = 255;
//and repaint the screen.
repaint();
break;
}
case KeyEvent.VK_DOWN: {
// decrease the alpha level
alpha-=128;
if(alpha<0) alpha=0;
//and repaint the screen.
repaint();
break;
}
default: {
// do nothing
break;
}
}
}
public void keyTyped(KeyEvent key)
{
// Ignored
} public void keyReleased(KeyEvent key)
{
// Ignored
}
} HaviBackgroundController.java/***********************************************************************************
*
* THIS SOFTWARE IS COPYRIGHT STEVEN MORRIS 2002. ALL RIGHTS RESERVED
*
* THIS SOFTWARE IS FREE FOR NON COMMERCIAL USE FOR THE PURPOSE OF LEARNING MHP. ANY
* USE FOR OTHER PURPOSES IS PROHIBITED UNLESS WRITTEN AGREEMENT IS OBTAINED.
*
* DISTRIBUTION OF THIS CODE IS PROHIBITED
*/// Import the HAVi UI classes that we need for this
import org.havi.ui.HScreen;
import org.havi.ui.HBackgroundDevice;
import org.havi.ui.HBackgroundConfiguration;
import org.havi.ui.HBackgroundImage;
import org.havi.ui.HStillImageBackgroundConfiguration;
import org.havi.ui.HConfigurationException;
import org.havi.ui.HPermissionDeniedException;
import org.havi.ui.HBackgroundConfigTemplate;
// Since some of the graphics configuration requires scarce resources, we
// need to use the DAVIC resource notification API
import org.davic.resources.*;/**
* This class handles the display of background images in an easy-to
* use way. Setting this up can be quite complex, and so in the case
* we've relegated it to a separate class to make it a little easier to
* understand.
*/
class HaviBackgroundController implements org.davic.resources.ResourceClient{ // The background device that we will use for displaying the image
private HBackgroundDevice backdevice; // The configuration for that background device
private HStillImageBackgroundConfiguration backconfig;
/**
* This method will initialise the video and graphics devices to allow
* them to display the background image.
*/
public boolean init()
{
// We first need to get the background device that we will use for
// displaying the image. To do this, we need to first decide which
// HScreen we will use. In this case (and most others), we will use
// the default one.
HScreen screen = HScreen.getDefaultHScreen();
// Once we have that, we get the default background device for that HScreen
HBackgroundDevice backdevice = screen.getDefaultHBackgroundDevice(); // Once we have a reference to the device, we can get a configuration for it.
// Get a configuration that we can use
HBackgroundConfigTemplate backgroundConfigurationTemplate = new
HBackgroundConfigTemplate();
backgroundConfigurationTemplate.setPreference(
HBackgroundConfigTemplate.FLICKER_FILTERING,
HBackgroundConfigTemplate.REQUIRED); HBackgroundConfiguration backconfig;
backconfig = backdevice.getBestConfiguration(
backgroundConfigurationTemplate);
// Can we reserve the device so that we can change the settings on it?
if (backdevice.reserveDevice(this))
{
// If we can, we set the configuration of the background device to
// the one we got above - this is the default configuration for
// this device.
try
{
backdevice.setBackgroundConfiguration(backconfig);
}
catch (Exception ex)
{
System.out.println("Can't initialise the background device");
// Release the device so that other applications can use it, if necessary.
backdevice.releaseDevice();
return false;
} // We need to check if we can put an image in the background in
// this configuration, since we can't do this in every configuration.
if(backconfig instanceof HStillImageBackgroundConfiguration)
{
// We can use this
this.backconfig = (HStillImageBackgroundConfiguration)backconfig;
this.backdevice = backdevice;
return true;
}
else
{
// If we can't, we again release the device since it's
// no use to us.
backdevice.releaseDevice();
}
}
return false;
} /**
* Free the resources we needed to display background images.
* Some implementations leave the image there, but there is an explicit
* warning in the MHP specification that this may not happen on all
* implementations. If you want to be sure that your image is still
* visible, don't do this.
*/
public void dispose()
{
// Check if we have something to dispose of
if (backdevice != null)
{
// RZlease the device and clear any references
backdevice.releaseDevice();
backdevice = null;
backconfig = null;
}
}
/**
* Display a background image
*/
public void display(String filename)
{
// Check we have the resources we need to display a background image
if(backconfig != null) {
// Create a new background image. The image is loaded from the
// filename that we pass in.
HBackgroundImage backimage = new HBackgroundImage(filename); // Now display the image. This can throw several exceptions, so we
// enclose it in a 'try' block
try {
backconfig.displayImage(backimage);
}
catch (java.io.IOException ioe) {
// Ignore it, but print a message to tell the user what's happened.
System.out.println("Can't display background image - IO exception");
ioe.printStackTrace();
}
catch (HPermissionDeniedException hpde) {
// We don't have permission to displayan image. We just ignore it.
System.out.println("Can't display background image - permission denied");
}
catch (HConfigurationException hce) {
// We don't have permission to displayan image. We just ignore it.
System.out.println("Can't display background image - configuration exception");
hce.printStackTrace();
}
}
} /**************************************************************************
*
* These methods are inherited from the ResourceClient interface and are used
* to tell the application when it has lost access to its resources (or
* when it is about to lose access to them). This gives the application a
* chance to clean up when it loses access to a resource, and gives it a
* chance to handle things gracefully.
*/ /**
* This method gets called when the resource manager requests that we give
* up a resource. We can refuse to do so, and that's what we do in this
* case (even though we shouldn't).
*/
public boolean requestRelease(ResourceProxy proxy, Object requestData) {
return false;
} /**
* This method gets called when the resource manager informs us that we must
* release a resource
*/
public void release(ResourceProxy proxy) {
// release control of the background device
backdevice.releaseDevice();
} /**
* This method gets called when the resource manager tells us we've
* lost access to a resource and we should clean up after ourselves.
*/
public void notifyRelease(ResourceProxy proxy) {
// release control of the background device. Even though we don't
// have control of it, this makes sure everything is synchronized.
backdevice.releaseDevice();
}
}