package net.xoetrope.swt;
import java.io.Reader;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import net.xoetrope.xml.XmlElement;
import net.xoetrope.xml.XmlSource;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Region;
/**
* <p>
* A widget for displaying an image and associating hotspots at coordinates
* specified in an external file
* </p>
* <p>
* Copyright: Copyright (c) Xoetrope Ltd., 1998-2003<br>
* License: see license.txt
*
* @version 1.0
*/
public class XHotspotImage extends XImage implements MouseMoveListener
{
/**
* true to draw the hotspots as highlighted areas
*/
protected int currentHotspotIdx;
/**
* The default pointer - the hand cursor
*/
protected static Cursor handCursor;
/**
* The default cursor
*/
protected static Cursor defaultCursor;
/**
* The hotspots
*/
protected Vector hotspots;
/**
* The hotspot names
*/
protected Vector names;
/**
* The hotspot tooltiptexts
*/
protected Vector tooltips = new Vector();
/**
* Constructor. Sets cursors and creates the Vector which stores the hotspots.
* Adds a new MouseListener to the image
*
* @param parent
* parent object
*/
public XHotspotImage( Object parent )
{
super( parent );
if ( handCursor == null ) {
handCursor = new Cursor( getDisplay(), SWT.CURSOR_HAND );
defaultCursor = new Cursor( getDisplay(), SWT.CURSOR_ARROW );
}
hotspots = new Vector();
addMouseMoveListener( this );
addMouseTrackListener( new MouseTrackAdapter()
{
public void mouseExit( MouseEvent e )
{
currentHotspotIdx = -1;
redraw();
}
} );
}
/**
* Refresh the display when the mouse moves
*/
public void mouseMove( MouseEvent e )
{
int numRegions = hotspots.size();
for ( int i = 0; i < numRegions; i++ ) {
Vector v = (Vector)hotspots.elementAt( i );
int numPolygons = v.size();
Region r = new Region();
for ( int j = 0; j < numPolygons; j++ ) {
int[] poly = (int[])v.elementAt( j );
r.add( poly );
}
if ( r.contains( e.x, e.y ) ) {
if ( i != currentHotspotIdx ) {
currentHotspotIdx = i;
setCursor( handCursor );
setToolTipText( (String)tooltips.get( i ) );
redraw();
}
return;
}
}
currentHotspotIdx = -1;
setCursor( defaultCursor );
setToolTipText( "" );
redraw();
}
/**
* Check the mouse event with the hotspots
*
* @param e
* MouseEvent
* @return index of the hotspot
*/
public int checkHotspot( MouseEvent e )
{
return currentHotspotIdx;
}
/**
* Add hotspots
*
* @param pts
* hotspots
*/
private void addHotspot( String pts )
{
StringTokenizer tokenizer = new StringTokenizer( pts, "," );
Vector v = new Vector();
boolean end = false;
int t[] = new int[tokenizer.countTokens() + 2];
int i = 0;
int x0 = getNextTokenAsInt( tokenizer );
int y0 = getNextTokenAsInt( tokenizer );
t[ i++ ] = x0;
t[ i++ ] = y0;
int x, y;
while ( tokenizer.hasMoreTokens() ) {
x = getNextTokenAsInt( tokenizer );
y = getNextTokenAsInt( tokenizer );
t[ i++ ] = x;
t[ i++ ] = y;
if ( x == x0 && y == y0 ) {
int tab[] = new int[i];
System.arraycopy( t, 0, tab, 0, i );
v.addElement( tab );
if ( tokenizer.hasMoreTokens() ) {
i = 0;
x0 = getNextTokenAsInt( tokenizer );
y0 = getNextTokenAsInt( tokenizer );
t[ i++ ] = x0;
t[ i++ ] = y0;
}
else
end = true;
}
}
if ( !end ) {
// Close the polygon
int tab[] = new int[i + 2];
System.arraycopy( t, 0, tab, 0, i );
tab[ i++ ] = x0;
tab[ i++ ] = y0;
v.addElement( tab );
}
hotspots.addElement( v );
}
/**
* Get the integer value of the next element
*
* @param tokenizer
* StringTokenizer
*/
private int getNextTokenAsInt( StringTokenizer tokenizer )
{
String s = tokenizer.nextToken().trim();
return Integer.parseInt( s );
}
/**
* Read a file to store the hotspots
*
* @param r
* Reader
*/
public void read( Reader r )
{
names = new Vector();
hotspots = new Vector();
XmlElement element = XmlSource.read( r );
if ( ( element == null ) || ( element.getChildren() == null ) )
return;
Enumeration e = element.getChildren().elements();
while ( e.hasMoreElements() ) {
XmlElement ele = (XmlElement)e.nextElement();
if ( ele.getName().compareTo( "area" ) == 0 ) {
Object name = ele.getAttribute( "name" );
if ( name == null )
names.addElement( "" );
else
names.addElement( ele.getAttribute( "name" ) );
addHotspot( ele.getAttribute( "coords" ) );
tooltips.addElement( ele.getAttribute( "tooltip" ) );
}
else
addCustomHotspot( ele );
}
}
/**
* Add a custom hotspot
*
* @param ele
* XmlElement
*/
protected void addCustomHotspot( XmlElement ele )
{
}
/**
* Get the name of a hotspot
*
* @param i
* index of the hotspot
* @return name
*/
public String getName( int i )
{
if ( i != -1 )
return (String)names.elementAt( i );
return null;
}
}