package net.xoetrope.html;
import netscape.javascript.JSObject;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.net.URL;
import net.xoetrope.data.XDataSource;
import net.xoetrope.debug.DebugLogger;
import net.xoetrope.xui.XComponentConstructor;
import net.xoetrope.xui.XComponentFactory;
import net.xoetrope.xui.XContentHolder;
import net.xoetrope.xui.PageSupport;
import net.xoetrope.xui.XPage;
import net.xoetrope.xui.XPageLoader;
import net.xoetrope.xui.XPageManager;
import net.xoetrope.xui.XProject;
import net.xoetrope.xui.XProjectManager;
import net.xoetrope.xui.build.BuildProperties;
/**
* <p>
* This class is constructed with a window or frame and can be part of an applet
* or an application. The class acts as the main entry point to an XUI
* application and provides some of the infrastructure needed to support the
* application.
* </p>
* <p>
* The applet can provide support for a frameset or a single page. Page display
* functions are also supported to allow the application to display more than a
* single page or change the page that is displayed.
* </p>
* <p>
* By choosing either the AWT or Swing version of the XApplet you choose to have
* either an AWT or a Swing application/applet. In general once this choice has
* been made you should not mix toolkits.
* </p>
* <p>
* Copyright (c) Xoetrope Ltd., 1998-2004<br>
* License: see license.txt
*
* @version $Revision: 1.3 $
*/
public class XApplet extends javax.swing.JApplet
{
// - Start of HTML Specific members ------------------------------------------
protected JSObject win, doc;
// - End of HTML Specific members --------------------------------------------
private static XHtmlPage currentPage;
private static XApplet applet;
protected XPageManager pageMgr;
protected XDataSource modelDataSource;
protected static Class defaultSourceClass = net.xoetrope.data.XDataSource.class;
protected int clientWidth = 800;
protected int clientHeight = 600;
private XProject currentProject;
protected static String[][] values;
protected static int index = 1;
public void XApplet()
{
System.out.println( "In html/XApplet" );
}
/** Initializes the applet XApplet */
public void init()
{
System.out.println( "In init" );
applet = this;
try {
java.awt.EventQueue.invokeAndWait( new Runnable()
{
public void run()
{
HtmlWidgetAdapter.getInstance();
String args[] = new String[1];
args[ 0 ] = "startup.properties";
applet.setup( args );
win = JSObject.getWindow( XApplet.getApplet() );
doc = (JSObject)win.getMember( "document" );
pageMgr = currentProject.getPageManager();
initComponents();
}
} );
}
catch ( Exception ex ) {
ex.printStackTrace();
}
}
public void callMethod( String methodName )
{
System.out.println( "In callMethod 1" );
XHtmlPage page = getCurrentPage();
try {
/** @todo use ReflectionHelper */
Class[] params = new Class[0];
Object[] args = new Object[0];
Method m = page.getClass().getMethod( methodName, params );
m.invoke( page, args );
}
catch ( NoSuchMethodException e ) {
e.printStackTrace();
}
catch ( Exception ee ) {
ee.printStackTrace();
}
}
public void setPageClass( String pageClassName )
{
System.out.println( "In setCurrentPage 1" );
currentPage = (XHtmlPage)pageMgr.loadPage( pageClassName );
}
public XHtmlPage getCurrentPage()
{
// if ( currentPage == null )
// currentPage = new Mortgage();
return currentPage;
}
/**
* Stores the values entered in the edit fields in a static String[][].
*
* @param id
* the id of the edit field (MUST be the same as one of the values in
* the first column of the static String[][]).
* @param value
* the value to be saved.
* @todo export these values to an xml file once the application is closed.
*/
public void storeValues( String id, String value )
{
if ( values == null ) {
values = new String[6][10];
values[ 0 ][ 0 ] = "titleList";
values[ 1 ][ 0 ] = "firstnameText";
values[ 2 ][ 0 ] = "surnameText";
values[ 3 ][ 0 ] = "dobText";
values[ 4 ][ 0 ] = "propValueText";
values[ 5 ][ 0 ] = "mortAmtText";
}
for ( int i = 0; i < values.length; i++ ) {
if ( values[ i ][ 0 ].equals( id ) ) {
if ( index != 1 && values[ i ][ index - 1 ] == null ) {
values[ i ][ index - 1 ] = value;
}
else {
values[ i ][ index ] = value;
index++;
}
}
}
}
/**
* @todo replace this with a call to the XProject.getObject();
*/
public static XApplet getApplet()
{
return applet;
}
/**
* Setup the applet by setting paths and then initializing the applet. This
* method is a stand-in for the main method, processing the commandline
* parameters, so that its work is reusable and does not needed to be redone
* by derived classes. This method should not be called directly by user code.
*
* @param frame
* the owner frame
* @param args
* the command line arguments
*/
protected void setup( String[] args )
{
String classPackageName = args.length > 1 ? args[ 1 ] : XPage.XUI_HTML_PACKAGE;
XComponentFactory.setRequiresParent( true );
/** @todo fix this and remove the call to getCurrentProject with null */
currentProject = XProjectManager.getCurrentProject( null );
currentProject.setPackageName( classPackageName );
currentProject.setEventHandlerClass( "net.xoetrope.html.XHtmlEventHandler" );
setResourceFile( args.length > 0 ? (String)args[ 0 ] : "startup.properties" );
currentProject.setStartupParam( "DefaultClass", "net.xoetrope.html.XHtmlPage" );
XPageLoader pageLoader = getSecondaryClassLoader( classPackageName );
if ( pageLoader != null )
currentProject.getPageManager().addSecondaryLoader( pageLoader );
/** @todo fix this */
String icon = currentProject.getStartupParam( "Icon" );
if ( icon != null )
;// shell.setIconImage( currentProject.getImage( icon ) );
initialise( win );
}
/**
* <p>
* Construct a new builder and set the default package. XUI sometimes uses
* additional class loaders to find the resources needed in a project. By
* default XUI uses the XuiBuilder class loader to convert XML files to Java
* classes.
* </p>
* <p>
* A custom class loader can be referenced in the startup properties file
* using the 'BuilderClass' property. Once this property has been determined
* this method will instantiate an instance of that class if necessary.
*
* @param packageName
* the name of the default widget package e.g. net.xoetrope.awt, this
* is normally defined as a result of choosing the appropriate
* version of the XApplet class
*/
protected XPageLoader getSecondaryClassLoader( String packageName )
{
String builderClass = currentProject.getStartupParam( "BuilderClass" );
Class pageLoaderClass = null;
if ( builderClass != null ) {
try {
pageLoaderClass = Class.forName( builderClass.trim() );
}
catch ( Exception ex ) {
DebugLogger.logError( "Unable to load builder class: " + ex.getMessage() );
}
}
// Load the default class if nothing else loaded
if ( pageLoaderClass == null ) {
try {
pageLoaderClass = Class.forName( "net.xoetrope.builder.XuiBuilder" );
}
catch ( Exception ex ) {
ex.printStackTrace();
}
}
try {
Class[] types = new Class[1];
Object[] args = new Object[1];
types[ 0 ] = XProject.class;
args[ 0 ] = currentProject;
Constructor ctor = pageLoaderClass.getConstructor( types );
XPageLoader pageLoader = (XPageLoader)ctor.newInstance( args );
pageLoader.setPackageName( packageName );
return pageLoader;
}
catch ( Exception ex ) {
}
DebugLogger.logError( "Unable to load XuiBuilder class" );
return null;
}
/**
* Sets the default datasource class. The default data source will be used to
* provide any initial data for the XModel. Normally this data is static data
* that will be used to populate things like lists and provide default values.
*
* @param className
* the name of the datasource class e.g.
* net.xoetrope.data.XDataSource.class, this class reads data from an
* XML file
*/
public static void setDefaultDataSource( String className )
{
try {
defaultSourceClass = Class.forName( className.trim() );
}
catch ( ClassNotFoundException ex ) {
}
}
/**
* Setup the default resource file for the application and load some of the
* information in it. The resource file is the startup properties file
*
* @param startFile
* The name of the file to be loaded, by default startup.properties
*/
protected void setResourceFile( String startFile )
{
currentProject.initialise( startFile );
try {
// String sUseWindow = currentProject.getStartupParam( "UseWindow" );
String temp = currentProject.getStartupParam( "ClientWidth" );
if ( temp != null )
clientWidth = Integer.parseInt( temp );
temp = currentProject.getStartupParam( "ClientHeight" );
if ( temp != null )
clientHeight = Integer.parseInt( temp );
// Check for subclassing of the datasource/model
temp = currentProject.getStartupParam( "XDataSourceClass" );
if ( temp != null ) {
try {
defaultSourceClass = Class.forName( temp.trim());
}
catch ( Exception ex ) {
}
}
}
catch ( Exception ex ) {
}
}
/**
* Gets the Frame containing the applet.
*
* @return Frame which is the applet or application's parent
*/
public Object getFrame()
{
return null;
}
/**
* <p>
* Generic function which is called from the constructor if it's an
* application or from start if its an applet.
* </p>
* The initialization process proceeds in the following order<br>
* <ol>
* <li>Register the component factories</li>
* <li>Setup the project class</li>
* <li>Setup the page manager</li>
* <li>Setup the resource manager</li>
* <li>Setup the style manager</li>
* <li>Size the main window</li>
* <li>Set the layout</li>
* <li>Add a shutdown hook</li>
* <li>Display the main window</li>
* </ol>
*
* @param f
* The Frame which acts as the parent.
* @param skipReset
* Lets the application know whether to skip resetting the style
* manager
*/
protected void initialise( JSObject s )
{
register();
// clientShell = s;
currentProject.getPageManager();
try {
URL db = getDocumentBase();
currentProject.setDocumentBase( db );
}
catch ( Exception e ) {
}
// XStyleManager styleMgr = XProjectManager.getStyleManager();
if ( s != null )
// s.setSize( clientWidth, clientHeight );
// setSize( new Dimension( clientWidth, clientHeight ) );
//
// appWindow = null;
// if ( bUseWindow ) {
// appWindow = new Window( f );
// appWindow.setSize( clientWidth, clientHeight );
// appWindow.addWindowListener( this );
// f.addWindowListener( this );
// }
// else {
// if ( f != null )
// appWindow = f;
// f.addWindowListener( this );
// }
// clientShell.setLayout( new RowLayout());
// setLayout( new BorderLayout());
currentProject.setObject( "Applet", this );
// currentProject.setObject( "ClientShell", win );
// currentProject.setObject( "Display", doc );
// Try to create the shutdown hook, this is not supported on all VMss
// try {
// Object shutdownHook = Class.forName(
// "net.xoetrope.xui.build.conditional.ShutdownHook" ).newInstance();
//
// // Try to register a listener for the startup and shutdown events.
// String lifeCycleObjectName = currentProject.getStartupParam(
// "LifeCycleListener" );
// if (( lifeCycleObjectName != null ) && ( lifeCycleObjectName.length() > 0
// )) {
// XLifeCycleListener lifeCycleObject = (XLifeCycleListener)Class.forName(
// lifeCycleObjectName ).newInstance();
// lifeCycleObject.initialize();
//
// Class params[] = new Class[ 1 ];
// Object args[] = new Object[ 1 ];
// params[ 0 ] = XLifeCycleListener.class;
// args[ 0 ] = lifeCycleObject;
// Method method = shutdownHook.getClass().getMethod(
// "addLifeCycleListener", params );
// method.invoke( shutdownHook, args );
// }
// }
// catch ( Exception ex ) {
// ex.printStackTrace();
// }
// Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
// if ( bUseWindow ) {
// Dimension frameSize = appWindow.getSize();
// appWindow.setLocation( ( screenSize.width - frameSize.width ) / 2, (
// screenSize.height - frameSize.height ) / 2 );
// appWindow.setVisible( true );
// f.setLocation( screenSize.width / 2, screenSize.height / 2 );
// f.setSize( 0,0 );
// f.setVisible( true );
// }
// else if ( s != null ) {
// Dimension frameSize = f.getSize();
// String center = currentProject.getStartupParam( "CenterWin" );
// if ( ( center != null ) && ( center.compareTo( "true" ) == 0 ) )
// f.setLocation( ( screenSize.width - frameSize.width ) / 2, (
// screenSize.height - frameSize.height ) / 2 );
// f.setVisible( true );
// }
setContent( s );
// if ( appWindow != null ) {
// appWindow.invalidate();
// appWindow.validate();
// appWindow.repaint();
// }
// clientShell.pack();
// clientShell.open();
// while ( !clientShell.isDisposed()) {
// if ( !display.readAndDispatch())
// display.sleep();
// }
// dispose();
}
/**
* Load the componentFactories by reading the factory names from the startup
* file. The value of the 'NumComponentFactories' is first read and then the
* value of ComponentFactory<X> (i.e. ComponentFactory0, ComponentFactory1)
* where <X> is the number, starting at zero, of the factory. Each factory is
* then instantiated and will be called upon to construct components in the
* order in which the factories were registered.
*/
protected void register()
{
int numFactories = 0;
String numFactoriesStr = currentProject.getStartupParam( "NumComponentFactories" );
if ( numFactoriesStr != null )
numFactories = new Integer( numFactoriesStr ).intValue();
for ( int i = 0; i < numFactories; i++ ) {
String factoryName = currentProject.getStartupParam( "ComponentFactory" + i );
try {
if ( factoryName != null )
XComponentFactory.registerComponentFactory( factoryName, (XComponentConstructor)Class.forName( factoryName.trim() ).newInstance() );
}
catch ( Exception ex ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "Factory not loaded: " + ex.getMessage() );
}
}
}
/**
* Load the content into the model. In the process an instance of the default
* model data source class is instantiated and reads data from a file pointed
* to by the 'ModelData' startup parameter.
*
* @param f
* the frame
*/
protected void setContent( JSObject s )
{
// boolean sourceExists = false;
try {
modelDataSource = (XDataSource)defaultSourceClass.newInstance();
}
catch ( Exception ex2 ) {
return;
}
try {
String fileName = currentProject.getStartupParam( "ModelData" );
if ( fileName != null ) {
try {
modelDataSource.read( currentProject.getBufferedReader( fileName, null ) );
}
catch ( Exception ex3 ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "Could not access file:" + fileName );
}
}
}
catch ( Exception ex ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "Exception in setContent" );
}
// try {
// if ( s != null )
// s.setText( currentProject.getStartupParam( "Title" ) );
// }
// catch ( Exception ex1 ) {
// ex1.printStackTrace();
// }
setHome();
}
/**
* Set the home page using the startup properties. The home page is
* established by combining the two startup properties 'StartPackage' and
* 'StartClass'. By default 'StartClass' is set to a value of 'home. Both
* startup parameters are optional. Loads the first page for the application.
*/
public void setHome()
{
try {
String packageName = currentProject.getStartupParam( "StartPackage" );
String homePage = currentProject.getStartupParam( "StartClass" );
if ( ( packageName == null ) && ( homePage == null ) )
homePage = "home";
if ( packageName != null )
packageName += ".";
pageMgr = currentProject.getPageManager();
pageMgr.setPackageName( packageName );
// pageMgr.setPageDisplay( this );
// if ( homePage != null )
// pageMgr.showPage( homePage );
}
catch ( Exception ex ) {
ex.printStackTrace();
}
}
/**
* Called when a page has been added or shown via the XPageManager. The page
* manager then requests that the applet/application then displays the page in
* the appropriate location.
*
* @param page
* The XPage which has been loaded.
* @return the page being displayed
*/
public PageSupport displayPage( PageSupport page )
{
return displayPage( page, null );
}
/**
* <p>
* Called when a page has been added or shown via the XPageManager. The page
* manager then requests that the applet/application then displays the page in
* the appropriate location.
* </p>
* <p>
* The sequence with which the page transition occurs is as follows:
* </p>
* <li>Find the appropriate target area</li>
* <li>Ask the page to make its components non visible (to avoid flicker
* during the page update)</li>
* <li>Set the page size</li>
* <li>Save the current page's data by calling 'saveBoundComponentValues</li>
* <li>Mark the current page as deactivated, and call the page's
* deactivated() method</li>
* <li>Remove the old page from the container</li>
* <li>Add the new page</li>
* <li>Update the new page's bindings by calling updateBindings()</li>
* <li>Update the new page's data by calling updateBoundComponentValues()</li>
* <li>Layout the container and request it to repaint</li>
* <li>Show the new page</li>
* <li>Mark the new page as activated, and call its pageActivated method</li>
* <ol>
* </ol>
*
* @param page
* The XPage which has been loaded.
* @param target
* the area to update
* @return the page being displayed
*/
public PageSupport displayPage( PageSupport pageObj, String target )
{
XHtmlPage page = (XHtmlPage)pageObj;
// XHtmlTarget targetContainer = findTarget( target );
page.showComponents( page, false, 0 );
page.setSize( clientWidth, clientHeight );
XHtmlPage lastPage = null;
// try {
// JSObject c = targetContainer.getComponent( 0 );
// if ( !( c instanceof XPage )) // The first component might be a tooltip
// targetContainer.remove( 0 );
// lastPage = ( XHtmlPage )targetContainer.getChildren()[ 0 ];
// }
// catch ( Exception e ) {}
if ( page != lastPage ) {
if ( lastPage != null ) {
lastPage.saveBoundComponentValues();
lastPage.setStatus( net.xoetrope.xui.XPage.DEACTIVATED );
try {
lastPage.pageDeactivated();
}
catch ( Exception ex ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "The pageDeactivated method could not be invoked due to an exception" );
}
// lastPage.setParent( hiddenPage );//targetContainer.remove( lastPage
// );
// targetContainer.layout();
}
// page.setParent( targetContainer );//targetContainer.add( page, "CENTER"
// );
page.updateBindings();
page.updateBoundComponentValues();
// targetContainer.layout();
// page.layout();
}
else {
page.updateBindings();
page.updateBoundComponentValues();
}
// targetContainer.layout();
page.setVisible( true );
page.showComponents( page, true, 0 );
// page.redraw();
// page.layout();
// page.setStatus( net.xoetrope.xui.XPage.ACTIVATED );
// try {
// page.pageActivated();
// }
// catch ( Exception ex ) {
// if ( BuildProperties.DEBUG ) {
// DebugLogger.logError( "The pageActivated method could not be invoked due
// to an exception" );
// ex.printStackTrace();
// }
// }
return page;
}
/**
* Remove the page from container. The page is simply removed and the
* container validated.
*
* @param page
*/
public void hidePage( JSObject page )
{
// XHtmlPage lastPage = null;
// Shell container = clientShell;
//
// try {
// JSObject c = container.getChildren()[ 0 ];
// lastPage = (XHtmlPage)container.getChildren()[ 0 ];
//
// if ( ( lastPage != null ) && ( page != lastPage ) ) {
// lastPage.setParent( hiddenPage );
//
// page.setStatus( net.xoetrope.xui.XPage.DEACTIVATED );
// page.pageDeactivated();
//
// container.layout();
// }
// }
// catch ( Exception e ) {
// if ( BuildProperties.DEBUG )
// DebugLogger.logError( "The page could not be hidden due to an exception:
// " + e.getMessage() );
// }
}
/**
* Finds the target area for a page display request, this only applies to a
* frameset. If there is no frameset the main area or default area is named
* 'content' and this area is used if null is used as the target name.
*
* @param target
* the target area name
* @return the container to be updated
*/
public XHtmlTarget findTarget( String target )
{
// JSObject targetContainer = this;
// if ( target == null )
// target = BuildProperties.CONTENT_TARGET;
//
// JSObject[] comps = targetContainer.getChildren();
// int numChildren = comps.length;
// for ( int i = 0; i < numChildren; i++ ) {
// if ( ((String)comps[ i ].getData( "Name" )).compareTo( target ) == 0 )
// return ( XHtmlTarget )comps[ i ];
// }
return null;// targetContainer;
}
/**
* Get the target for a page display request. The target areas are stored in
* the order in which they were declared or added.
*
* @param idx
* the target area
* @return the container to be updated
*/
public XHtmlTarget getTarget( int idx )
{
// JSObject targetContainer = this;
// JSObject[] comps = targetContainer.getChildren();
// int numChildren = comps.length;
return null;// ( XHtmlTarget )comps[ idx ];
}
/**
* Get the number of target areas in the container
*/
public int getNumTargets()
{
// JSObject targetContainer = this;
return -1;// targetContainer.getChildren().length;
}
/**
* Add a new frame or target area to a frameset
*
* @param name
* the frame name
* @param constraint
* the BorderlayoutConstraint
* @param preferredWidth
* the preferred width
* @param preferredHeight
* the preferred height
* @param return
* the new target
*/
public XContentHolder addTarget( String name, Object constraint, int preferredWidth, int preferredHeight )
{
// JSObject root = this;
// XHtmlTarget container = new XHtmlTarget( this, name, preferredWidth,
// preferredHeight );
// container.setParent( root );
return null;// container;
}
/**
* Exit the application
*/
// public void windowClosing( WindowEvent e )
// {
// System.exit( 0 );
// }
/**
* Get the width of the main window.
*/
public int getClientWidth()
{
return clientWidth;
}
/**
* Get the height of the main window.
*/
public int getClientHeight()
{
return clientHeight;
}
/**
* Set the menubar.
*
* @param mb
*/
public static void setMenuBar( Object mb )
{
// clientShell.setMenuBar( mb );
}
/**
* Get the menubar.
*/
public static Object getMenuBar()
{
return null;// clientShell.getMenuBar();
}
/**
* Template method, unused at present
*/
// public void windowActivated( WindowEvent e )
// {}
/**
* Template method, unused at present
*/
// public void windowClosed( WindowEvent e )
// {}
/**
* Template method, unused at present
*/
// public void windowDeiconified( WindowEvent e )
// {}
/**
* Template method, unused at present
*/
// public void windowDeactivated( WindowEvent e )
// {}
/**
* Template method, unused at present
*/
// public void windowIconified( WindowEvent e )
// {}
/**
* Template method, unused at present
*/
// public void windowOpened( WindowEvent e )
// {}
public URL getDocumentBase()
{
try {
return super.getDocumentBase();
}
catch ( Exception e ) {
return null;
}
}
/**
* This method is called from within the init() method to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code
// ">//GEN-BEGIN:initComponents
private void initComponents()
{
jLabel1 = new javax.swing.JLabel();
setBackground( new java.awt.Color( 222, 40, 76 ) );
jLabel1.setBackground( new java.awt.Color( 204, 0, 0 ) );
jLabel1.setForeground( new java.awt.Color( 255, 153, 0 ) );
jLabel1.setText( "TESTING" );
getContentPane().add( jLabel1, java.awt.BorderLayout.NORTH );
}
// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel jLabel1;
// End of variables declaration//GEN-END:variables
}