package oracle.forms.enhancedItems;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import oracle.forms.ui.VButton;
import oracle.forms.handler.IHandler;
import oracle.forms.properties.ID;
import oracle.forms.properties.Property;
/**
*
UTL VRNTK enhanced button
*
* This is a PJC that implements a web style Rollover image button
* where the image changes when the user moves the mouse over the component with ability to show label.
* The standard Forms oracle.forms.ui.VButton
is subclassed so only the additional
* functionality is required to be added.
*
* We register two new forms properties, IMAGE_NAME_ON and IMAGE_NAME_OFF. These properties form the
* the URL of the image files that the button will display. These properties will be set by PL/SQL
* trigger code or can be set by defining the LABEL of the button with the prefix [ROLLOVER] followed by
* the ON inage and OFF image names separated by a comma
*
* @version 1.0 09/13/1999 created
* @version 1.1 12/09/1999 modified to support 6i features to allow dynamic custom property manipulation
* @version 1.2 02/20/2000 removed 6.0 stuff and renamed package to oracle.forms.demos for distribution
* @version 2.0 09/24/2001 amemded for Forms 9i. Moved to the oracle.forms.demos.enhancedItems package. Made the setting of the on/off images declaritive, using the Label Property. Allowed loading from a JAR file as well as codebase.
* @version 3.0 17/02/2006 renamed to LabledIconButton. Extend functionality to show both label and image by reload of paint methods
* @author Steve Button, Duncan Mills, Oleh Tyshchenko
*/
public class LabledIconButton extends VButton
{
/**
* the property registered to specify the on image to be used
*/
public final static ID IMAGE_NAME_ON = ID.registerProperty("IMAGE_NAME_ON");
/**
* the property registered to specify the off image to be used
*/
public final static ID IMAGE_NAME_OFF = ID.registerProperty("IMAGE_NAME_OFF");
/**
* Forms property used to indicate that we want the utility to switch
* Messaging on to the Java Console so we can see what is going on
*/
private static final ID DEBUGMESSAGES = ID.registerProperty("DEBUGMESSAGES");
/**
* Forms property used to indicate that we want the utility to switch
* Messaging on to the Java Console for ALL INSTANCES of this PJC
* so we can see what is going on
* This will generate a LOT of messages
*/
private static final ID DEBUGMESSAGES_ALL = ID.registerProperty("DEBUGMESSAGES_ALL");
/**
* define ON
*/
private final int ON = 1;
/**
* define OFF
*/
private final int OFF = 0;
/**
* the classname used for debugging purposes
* use getClass().getName(); if you want the
* full package name
*/
private final String CLASSNAME = this.getDefaultName();
/**
* the hardcoded root directory for buttons in the JAR
*/
private final String JARBUTTONSDIR = "/";
/**
* the hardcoded button icon type in the JAR
*/
private final String JARBUTTONSEXT = ".gif";
/**
* the name of the on image
*/
private String m_imageNameOn;
/**
* the name of the off image
*/
private String m_imageNameOff;
/**
* storage for the handler for this class
*/
private IHandler m_handler;
/**
* The codebase from which the JAR was loaded - used to locate images
*/
private URL m_codeBase;
/**
* the current state ON | OFF
*/
private int m_state = OFF;
/**
* array to hold the images used to represent the state of the button
*/
private Image[] m_images = { null, null };
/**
* Boolean value which describes if the button is currently a rollover or
* if it is a general rounded button.
*/
private boolean m_isRollover = false;
/**
* do we want to debug for this class? Set this to true to see debug messages.
*/
private boolean m_debug = false;
/**
* do we want to debug for all instances of this class?
*/
private static boolean m_debugAll = false;
public LabledIconButton()
{
super();
log("Debugging on: Creating Button Instance");
setLeftmost(false);
setRightmost(false);
}
/**
* Implementation of IView interface which provides an initialization opportunity for the component
*
* @param handler - message handler associated with this view.
* @see oracle.forms.ui.IView
*/
public void init(IHandler handler)
{
m_handler = handler;
m_codeBase = handler.getCodeBase();
super.init(handler);
}
/**
* Implementation of IView interface which provides an custom paint ability
*
* @param handler - Graphics object to draw.
* @see java.awt.Graphics
*/
public void paint(Graphics p0)
{
int x = 5, y = 4;
log( "Paint " + p0.toString());
super.paint(p0);
// Do some adjustion for left rounded button
if (this.isLeftmost())
x = x + 5;
// Depend on current button state pick to draw one of the images
if (m_images[m_state] != null)
p0.drawImage(m_images[m_state],x,y,this);
}
/**
* Implementation of IView interface which sets a requested property to a given value
* If the property being set is LABEL then special processing is undertaken.
* If the Label is Prefixed with the string [ROLLOVER] then the rest of the label is assumed
* to be a comma separated list of the ON and OFF icon names trailed by button's label.
* If the String after the rollover tag does not contain a pair e.g. no comma
* then we assume that it's one of the Icons in the JAR which will be called
* xxx_on and xxx_off where xxx is the supplied string. We then set up the pair for
* you e.g. a label of [ROLLOVER]firstrec will cause the icons
* /oracle/forms/demos/images/firstrec_on.gif and
* /oracle/forms/demos/images/firstrec_off.gif to be loaded
* If the label does not begin with [ROLLOVER] then we treat it a a normal text label
* except that leading or trailing round brackets can be used to indicate if
* that edge of the button is rounded in Oracle look and feel
*
* The programmer can control the Rounded button look in Oracle Look and Feel
* by placing a round bracket at the start or the end (or both) of the label
*
* @param property property to be set.
* @param value value of the property id.
* @return true if the property could be set, false otherwise.
* @see oracle.forms.ui.IView
*/
public boolean setProperty(ID property, Object value)
{
if (property == ID.LABEL)
{
log("Setting Label to " + value.toString());
String label = value.toString().trim();
if (label.equals(""))
{
enableRollover();
return true;
}
if (label.startsWith("[ROLLOVER]"))
{
enableRollover();
label = label.substring(10);
int i = label.indexOf(",");
if (i > 0)
{
m_imageNameOn = JARBUTTONSDIR + label.substring(0,i) + JARBUTTONSEXT;
// Check if label specified
if (label.indexOf(",",i+2) > 0)
{
// Button's label specified
m_imageNameOff = JARBUTTONSDIR + label.substring(i+1,label.indexOf(",", i+2)) + JARBUTTONSEXT;
label = label.substring(label.indexOf(",", i+2)+1);
}
else
{
// Button's label doesn't specified
m_imageNameOff = JARBUTTONSDIR + label.substring(i+1) + JARBUTTONSEXT;
label = "";
}
}
else
{
m_imageNameOn = JARBUTTONSDIR + label + "_on" + JARBUTTONSEXT;
m_imageNameOff = JARBUTTONSDIR + label + "_off" + JARBUTTONSEXT;
}
log("Detected Image Names + ON='" + m_imageNameOn + "', OFF= '" + m_imageNameOff + "' LABEL '" + label + "'");
loadImage(ON,m_imageNameOn);
loadImage(OFF,m_imageNameOff);
setImage(OFF);
}
//If button's label beginig with ( round up the left edge
if (label.startsWith("("))
{
log("Rounding left edge of " + label);
setLeftmost(true);
label = label.substring(1);
}
//If button's label beginig with ) round up the right edge
if (label.endsWith(")"))
{
log("Rounding right edge of " + label);
setRightmost(true);
label = label.substring(0,label.length()-1);
}
return super.setProperty(property, label);
}
else if (property == IMAGE_NAME_ON)
{
// make sure we are in rollover mode
enableRollover();
log("setProperty - IMAGE_NAME_ON value=" + value.toString());
// load the requested image
loadImage(ON,m_imageNameOn);
m_state = ON;
// reset the currrently drawn image if needed
this.repaint();
return true;
}
else if (property == IMAGE_NAME_OFF)
{
// make sure we are in rollover mode
enableRollover();
log("setProperty - IMAGE_NAME_OFF value=" + value.toString());
// load the requested image
m_imageNameOff = (String) value;
loadImage(OFF,m_imageNameOff);
m_state = OFF;
// reset the currrently drawn image if needed
this.repaint();
return true;
}
else if (property == DEBUGMESSAGES)
{
if (value.toString().equalsIgnoreCase("true"))
m_debug = true;
else
m_debug = false;
log("Debugging " + m_debug);
return true;
}
else if (property == DEBUGMESSAGES_ALL)
{
if (value.toString().equalsIgnoreCase("true"))
m_debugAll = true;
else
m_debugAll = false;
log("Debugging " + m_debugAll);
return true;
}
else
{
return super.setProperty(property, value);
}
}
/**
* Implementation of IView interface which returns the value of a requested property
*
* @param pid the property id that represents the property to be set
* @return the value of the property id
* @see oracle.forms.ui.IView
*/
public Object getProperty(ID pid)
{
if ( pid == IMAGE_NAME_OFF )
{
return m_imageNameOff;
}
else if ( pid == IMAGE_NAME_ON )
{
return m_imageNameOn;
}
else
return super.getProperty(pid);
}
/**
* Loads the requested image from the Document base, loaded JAR files,
* or from the Codebase
* Here is a breakdown of the logic:
*
* - First we check the the loaded JAR files for the images
* - If it's not an inbuilt image, the code then checks the
* image name supplied for http or https, if that is present
* then it assumes the name is a full URL and loads the image from there.
* - If there is no Protocol in the image name then we assume it is a
* relative URL to the docbase of the machine that Forms is running on.
* We also pick up the protocol, and port and re-use those
* - If that fails to find the image, then we search relative to the
* codebase e.g. forms90/java
*
* @param which the image state to set, value values ON | OFF
* @param imageName the name of the image to load, including extension
*/
private void loadImage(int which, String imageName)
{
URL imageURL = null;
boolean loadSuccess = false;
//Current JAR
log("Searching JAR for " + imageName);
imageURL = getClass().getResource(imageName);
if (imageURL != null)
{
log("URL: " + imageURL.toString());
try
{
m_images[which] = Toolkit.getDefaultToolkit().getImage(imageURL);
loadSuccess = true;
log("Image found: " + imageURL.toString());
}
catch (Exception ilex)
{
log("Error loading image from JAR: " + ilex.toString());
}
}
else
{
log("Unable to find " + imageName + " in JAR");
}
//DOCBASE
if (loadSuccess == false)
{
log("Searching docbase for " + imageName);
try
{
if (imageName.toLowerCase().startsWith("http://")||imageName.toLowerCase().startsWith("https://"))
{
imageURL = new URL(imageName);
}
else
{
imageURL = new URL(m_codeBase.getProtocol() + "://" + m_codeBase.getHost() + ":" + m_codeBase.getPort() + imageName);
}
log("Constructed URL: " + imageURL.toString());
try
{
m_images[which] = createImage((java.awt.image.ImageProducer) imageURL.getContent());
loadSuccess = true;
log("Image found: " + imageURL.toString());
}
catch (Exception ilex)
{
log("Error reading image - " + ilex.toString());
}
}
catch (java.net.MalformedURLException urlex)
{
log("Error creating URL - " + urlex.toString());
}
}
//CODEBASE
if (loadSuccess == false)
{
log("Searching codebase for " + imageName);
try
{
imageURL = new URL(m_codeBase, imageName);
log("Constructed URL: " + imageURL.toString());
try
{
m_images[which] = createImage((java.awt.image.ImageProducer) imageURL.getContent());
loadSuccess = true;
log("Image found: " + imageURL.toString());
}
catch (Exception ilex)
{
log("Error reading image - " + ilex.toString());
}
}
catch (java.net.MalformedURLException urlex)
{
log("Error creating URL - " + urlex.toString());
}
}
if (loadSuccess == false)
log("Error image " + imageName + " could not be located");
}
/**
* Set the image displayed to the requested image if the requested image is the current image.
* Effectively does a redraw of the currently displayed image if the image is changed by the user.
*
* @param which the image state to draw, value values ON | OFF
* @param current the current state being represented by the image
*/
private void setImage(int which, int current)
{
if(which==current)
setImage(which);
}
/**
* Set the image displayed to the appropriate image depending on the user action.
*
* @param which the image to display, valid values ON and OFF
*/
private void setImage(int which)
{
m_state=which;
if(which==ON)
log("setImage ON");
else
log("setImage OFF");
}
/**
* Creates the mouse listener for rollover mode
* Also sets the button to fully rounded
*/
private void enableRollover()
{
if (!m_isRollover)
{
log("Enabling Rollover");
addMouseListener(new LabledIconButtonMouseAdapter());
m_isRollover = true;
}
}
/**
* Utility function to print out a debug message to the Java Console
* @param msg string to display, this will be prefixed with the classname of the PJC
*/
public void log(String msg)
{
if(m_debug||m_debugAll)
System.out.println(CLASSNAME + ": " + msg);
}
/**
* Private class to handle user mouse actions and to switch images when the
* user moves the mouse into and out of the button object.
*/
class LabledIconButtonMouseAdapter extends MouseAdapter
{
/**
* User moved the mouse over the button, swap to the on image.
*/
public void mouseEntered(MouseEvent me)
{
setImage(ON);
me.getComponent().repaint();
}
/**
* User moved the mouse out of the button, swap to the off image.
*/
public void mouseExited(MouseEvent me)
{
setImage(OFF);
me.getComponent().repaint();
}
}
}