Xoetrope
HomePage :: Categories :: PageIndex :: RecentChanges :: RecentlyCommented :: Login/Register

Upgrading to XUI 3.0


XUI 3.0 introduces many new features and capabilities designed to extend the scope of XUI, some of these changes have required changes to the APIs.

API changes
The biggest changes in XUI relate to the project sturcture. Prior to XUI 3.0 the XApplet class provided much of the infrastructure, however as XUI 3.0 expands the number of startup classes and startup styles the code in the class has been refactored into the XApplicationContext class. The second major change is the addition of support for multiple projects within the one JVM instance, this change provides support for construction of mudular applications, however, it required a better separation of project components. The upshot of these changes is that some APIs take an additional argument, a reference to a project.

Factories
Many of the factories in XUI have been redesigned to work with XML configuration files so that they can be extended more easily, and this change should have little impact of upgraded applications unless they rely on internal details of the factories. One side effect of the changes is that some of the internal factories are no longer required and have been dropped.

Event handlers
The event handling is one of those APIs affected by the above changes and has itself undergone significant changes. XUI 3.0 is better able to event types other than the built in types but at the price of changing the API. Gone from the core are the specific adder methods for the built in events and instead these events are configured from XML. In some cases however the events were added from Java code and this is now a little more difficult. To alleviate the problem we have added some helper classes to minimize the code changes and replicate the old way of working, see MigrationHelper in the deprecated packages. As we move toward completion of XUI 3.0, more of these upgrade helpers will be added.

Validations
The validations are setup by a single factory class that can take multiple configuration files, and therefore the initialization changes from:
  1.     try {
  2.       setValidationFactory( new XValidationFactory( project.getBufferedReader( "validate.xml", "UTF8" )) );
  3.     }
  4.     catch ( Exception ex ) {
  5.       ex.printStackTrace();
  6.     }

to
  1.     try {
  2.       setValidationFactory( new XValidationFactory( project ));
  3.     }
  4.     catch ( Exception ex ) {
  5.       ex.printStackTrace();
  6.     }

the new factory reads a validations.xml file from the project, in addition to the one included in XUI itself (see net/xoetrope/xui/validation/validations.xml).

Data bindings
Data bindings have undergone extensive changes in the upgrade to XUI 3.0, and if you have custom data bindings then you will need to change the implementation. In XUI 2.x the XDataBinding was an interface, but in XUI 3.0 this is changed to a abstract class, thus
  1. public class StaticBinding implements XDataBinding

becomes
  1. public class StaticBinding extends XDataBinding

and the new abstract class provides some additional members:
  1.   protected XProject currentProject;
  2.  
  3.   protected Object component;
  4.  
  5.   protected String sourcePath;
  6.   protected String outputPath;
  7.  
  8.   protected XModel sourceModel;
  9.   protected XModel outputModel;
  10.  
  11.   protected boolean reevaluate = true;


The new members are usually initialized when the setup method is invoked. The derived class should now invoke the XDataBinding.setupHelper(...) method when implementing the setup method so as to setup the base class. The method can also implement any setup specific to the individual binding:

  1. /**
  2.    * Setup and configure the binding instance. The binding is configured via the
  3.    * XML setup registered for the particular binding type and then, subsequently
  4.    * by attibitional attributes of the binding instance specified in the page
  5.    * declaration, for the individual binding instance. The binding may also
  6.    * obtain configuration or reference information from the component and the
  7.    * project.
  8.    * @param project the owning project
  9.    * @param c the component being bound
  10.    * @param bindingConfig the XML element which contains the binding configuration
  11.    * @param instanceConfig the XML element which contains the setup attributes of the binding instance
  12.    */
  13.   public void setup( XProject project,
  14.                       Object c,
  15.                       Hashtable bindingConfig,
  16.                       Hashtable instanceConfig )
  17.   {
  18.     // Setup the base class, setting all its members
  19.     setupHelper( project, c, bindingConfig, instanceConfig );
  20.  
  21.     // Do the local setup
  22.     Object obj = instanceConfig.get( "unitIdx" );
  23.     if ( obj != null )
  24.       unitIdx = ((Integer)obj).intValue();


Two Hashtables are passed to the setup method, the first originating from the bindings.xml file that declares the binding type (see net/xoetrope/xui/data/bindings.xml for an example). Each project can include a file to specify custom bindings in addition to the one build into XUI. The second Hashtable includes attributes from the binding declaration in the page XML.

Similarly, the XDataBindingFactory has changed from and interface to an abstract class and it now has responsibility for calling the bindings setup method, so the old XUI 2.x factory
  1. public class XUnitBindingFactory implements XDataBindingFactory
  2. {
  3.     public XDataBinding getBinding( PageSupport page, Object comp, XModel model, XmlElement bindingNode )
  4.     {
  5.           StaticBinding staticBinding = new StaticBinding();
  6.           staticBinding.setup( comp, bindingNode );
  7.           return staticBinding;
  8.     }

becomes
  1. public class XUnitBindingFactory extends XDataBindingFactory
  2. {
  3.   public XUnitBindingFactory( XProject project )
  4.   {
  5.     super( project );
  6.   }
  7.  
  8.     public XDataBinding getBinding( PageSupport page, Object comp, Hashtable instanceConfig )
  9.     {
  10.           StaticBinding staticBinding = new StaticBinding();
  11.           staticBinding.setup( currentProject, comp, null, instanceConfig );
  12.           return staticBinding;
  13.     }


Finally, instantiating the bindings is now a little harder due to the new interfaces and a set of helper (not yet finalized) methods have been added to ease the transition
  1.     addBinding( new XTextBinding( roomNumber, "load/currentLoad" ));
  2.     // becomes
  3.     addBinding( BindingHelper.newXTextBinding( roomNumber, "load/currentLoad" ));   


The BindingHelper class performs the following functions (this will be inserted into XUI 3.0 at some point in the future prior to release).
  1. package net.xoetrope.deprecated.binding.helper;
  2.  
  3. import java.awt.Component;
  4. import java.util.Hashtable;
  5. import net.xoetrope.optional.data.XLocalisedListBinding;
  6. import net.xoetrope.xui.XProjectManager;
  7. import net.xoetrope.xui.data.XDataBinding;
  8. import net.xoetrope.xui.data.XListBinding;
  9. import net.xoetrope.xui.data.XStateBinding;
  10. import net.xoetrope.xui.data.XTextBinding;
  11.  
  12. public class BindingHelper
  13. {
  14.   public static XDataBinding newXStateBinding( Object c, String source )
  15.   {
  16.     XStateBinding binding = new XStateBinding();
  17.     Hashtable instanceConfig = new Hashtable();
  18.     instanceConfig.put( "source", source );
  19.     instanceConfig.put( "sourcePath", source );
  20.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  21.     return binding;
  22.   }
  23.  
  24.   public static XDataBinding newXTextBinding( Object c, String source )
  25.   {
  26.     XTextBinding binding = new XTextBinding();
  27.     Hashtable instanceConfig = new Hashtable();
  28.     instanceConfig.put( "source", source );
  29.     instanceConfig.put( "sourcePath", source );
  30.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  31.     return binding;
  32.   }
  33.  
  34.   public static XDataBinding newXTextBinding( Object c, String source, String output )
  35.   {
  36.     XTextBinding binding = new XTextBinding();
  37.     Hashtable instanceConfig = new Hashtable();
  38.     instanceConfig.put( "source", source );
  39.     instanceConfig.put( "sourcePath", source );
  40.     instanceConfig.put( "output", output );
  41.     instanceConfig.put( "outputPath", output );
  42.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  43.     return binding;
  44.   } 
  45.  
  46.   public static XDataBinding newConversionTextBinding( Object c, String source, int units )
  47.   {
  48.     ConversionTextBinding binding = new ConversionTextBinding();
  49.     Hashtable instanceConfig = new Hashtable();
  50.     instanceConfig.put( "source", source );
  51.     instanceConfig.put( "sourcePath", source );
  52.     instanceConfig.put( "units", new Integer( units ));
  53.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  54.     return binding;
  55.   }
  56.  
  57.   public static XDataBinding newConversionTextBinding( Object c, String source, int units, int decimals )
  58.   {
  59.     ConversionTextBinding binding = new ConversionTextBinding();
  60.     Hashtable instanceConfig = new Hashtable();
  61.     instanceConfig.put( "source", source );
  62.     instanceConfig.put( "sourcePath", source );
  63.     instanceConfig.put( "units", new Integer( units ));
  64.     instanceConfig.put( "decimals", new Integer( decimals ));
  65.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  66.     return binding;
  67.   }
  68.  
  69.   public static XDataBinding newXLocalisedListBinding( Object c, String source )
  70.   {
  71.     XLocalisedListBinding binding = new XLocalisedListBinding();
  72.     Hashtable instanceConfig = new Hashtable();
  73.     instanceConfig.put( "source", source );
  74.     instanceConfig.put( "sourcePath", source );
  75.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  76.     return binding;
  77.   } 
  78.  
  79.   public static XDataBinding newXLocalisedListBinding( Object c, String source, String output )
  80.   {
  81.     XLocalisedListBinding binding = new XLocalisedListBinding();
  82.     Hashtable instanceConfig = new Hashtable();
  83.     instanceConfig.put( "source", source );
  84.     instanceConfig.put( "sourcePath", source );
  85.     instanceConfig.put( "output", output );
  86.     instanceConfig.put( "outputPath", output );
  87.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  88.     return binding;
  89.   } 
  90.    
  91.    
  92.   public static XDataBinding newXListBinding( Object c, String source )
  93.   {
  94.     XListBinding binding = new XListBinding();
  95.     Hashtable instanceConfig = new Hashtable();
  96.     instanceConfig.put( "source", source );
  97.     instanceConfig.put( "sourcePath", source );
  98.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  99.     return binding;
  100.   }
  101.  
  102.   public static XDataBinding newXListBinding( Object c, String source, String output )
  103.   {
  104.     XListBinding binding = new XListBinding();
  105.     Hashtable instanceConfig = new Hashtable();
  106.     instanceConfig.put( "source", source );
  107.     instanceConfig.put( "sourcePath", source );
  108.     instanceConfig.put( "output", output );
  109.     instanceConfig.put( "outputPath", output );
  110.     binding.setup( XProjectManager.getCurrentProject(), (Component)c, null, instanceConfig );
  111.     return binding;
  112.   }
  113. }


Event handling
The event handling has changed to allow registration of new event handlers. For the most part this change will not be visible to XUI users unless XUI event handlers are added directly from Java. In such cases the API is more complicated, and again some helper methods are added.

  1.     addMouseHandler( imgHome, "showHome" );
  2.     addMouseHandler( imgMoreInfo, "moreInfo" );
  3.     addMouseHandler( imgContinue, "nextScreen" );
  4.     addMouseHandler( imgBack, "previousScreen" );
  5.     addMouseHandler( roomImage, "handleHotspotsClicks" );
  6.     addItemHandler( cmbFloorType, "floorTypeChanged" );
  7.     addKeyHandler( txtFloorThickness, "floorThicknessChanged" );

becomes
  1.     MigrationHelper.addMouseHandler( this, imgHome, "showHome" );
  2.     MigrationHelper.addMouseHandler( this, imgMoreInfo, "moreInfo" );
  3.     MigrationHelper.addMouseHandler( this, imgContinue, "nextScreen" );
  4.     MigrationHelper.addMouseHandler( this, imgBack, "previousScreen" );
  5.     MigrationHelper.addMouseHandler( this, roomImage, "handleHotspotsClicks" );
  6.     MigrationHelper.addItemHandler( this, cmbFloorType, "floorTypeChanged" );
  7.     MigrationHelper.addKeyHandler( this, txtFloorThickness, "floorThicknessChanged" );


Widening of APIs
Many APIs now take a reference to the current project as an argument, for example new DatabaseTableModel(); becomes new DatabaseTableModel( project );. The change allows for better coordination of resources in the context of modular applications where two or more applications are loaded within the one JVM. Similarly
OLD NEW
new DatabaseTableModel() new DatabaseTableModel(project)
DatabaseTableModel.getTable('Voltages') DatabaseTableModel.getTable(project,'Voltages')
XModelHelper.get( rootNode, 'Type' ) XModelHelper.get( project, rootNode, 'Type' )


Deprecated APIs
Change the following imports
OLD NEW
import net.xoetrope.xui.helper.BuddyHelper import net.xoetrope.deprecated.xui.helper.BuddyHelper
import net.xoetrope.xui.data.XCustomDataBinding use the new XDataBinding interface


Access to the data model and other project members that were available should now be accessed via the current project. Thus the model can be accessed as
  1. rootModel from within a page
  2. getModel() from within the project

There are no comments on this page. [Add comment]

Page was generated in 1.4700 seconds