You are hereAria User Guide / Section III: In Depth / Component Factories
Component Factories
Working with components
At the heart of Aria is the component factory. The built-in component factory constructs the Aria components and comes in two flavours; one for Swing and one for AWT. Using component factories hides much of the detail of building individual components and makes it possible to change the implementation without having to change all the client code.
Aria allows component factories to be added and hence it can accommodate a wide range of components apart from the built-in set. Aria also includes a facility to register new components via an XML registry and even an editor for this registry
Choosing how to install components
Of the two methods of installing components, the XML registry is by far the simpler as you can simple use the interactive registry editor and its built-in component factory without any custom coding. The alternative is to build a custom component factory and directly instantiate the components.
While creating a component factory may be more work it also gives more control over the process of creating and initializing the components. Using a component factory you can achieve things that are not normally possible with the XML registered components, for example Aria's repeat element is implement via a special component factory.
Using the registry editor
The Integrated Component Registry Editor is a new feature in Aria 2.0
The component registry editor can be accessed by clicking the `*' button in the component palette toolbar. Almost all of Aria's non-core components are added via this registry so you can see how the properties of the indvidual components are configured.
The editor assumes that the components are held in Jar files and are represented as Java Beans. Upon opening the editor you may add or delete Jar libraries.
The editor then scans the Jar for suitable components and displays a hierarchical view of the available components. It is important to note that the editor does not automatically include any of the components or any of the component properties. It is up to you to tell the editor what to use.
The component properties are shown as an individual component is selected. You may rename the components so as to give it a tag that is suitable for use in an XML file. Then you can choose which methods to use as properties of an individual tag. Normally only the setter methods are used in the XML but you may also use the getter methods.
The methods may also be configured to be visible in various modes:
|
Mode |
Usage |
|---|---|
|
Novice |
A minimal set of properties for new users |
|
Normal |
A set of properties for normal everyday use |
|
Expert |
A fuller set of properties for detail component configuration. |
The idea of these modes is that reducing the number of visible properties makes it easier to locate commonly used properties. Fewer options may also make it easier for a novice to make use of the component.
Once the component and its properties have been chosen the editor generates a new
components.xml
file for the application. The component palette is also updated and the components can be used in the application.
The registry file for each project also acts as an overlay for the built-in registry files. Both
Aria Editor
and Aria include registry files for their own components. These registry files are loaded as the first page is loaded after startup of the project. Each project has its own configuration file so that its configuration is independant of other projects even though it loads data from the shared sources of built-in registry files.
Aria itself uses the registry for loading component Jar files and therefore an individual application may use components registered via several configuration files. Aria and
Aria Editor
each register components this way and your application itself may add another, so an application will typically have several component registration files. However, for the most part you need not worry about these details as they are all catered for by the built-in regsitry editor.
The registry editor can be used in one of two modes. The first - a simple mode, is used when the editor is opened normally. In this mode only the methods with types that Aria and Aria can construct directly from XML are allowed.
In the advanced mode, which can be accessed by holding down the
CTRL
key while opening the editor, all the methods are shown. In the advanced mode it is left to the user to ensure that the property values are correctly set. Normally this is ok if coding via Java, but it is difficult to achieve when using XML to define the pages.
The registration file generated by the registration editor is saved under the user profile. As a project is edited the registration file held in the project's
resources
folder is updated as is the project's IDE settings. In addtion any Jars required by the components added during editing of the project are copied to the project's
lib
folder and references in the project's IDE settings.
Installing a component factory
The factory needs to be registered with the main class, this is done through the
startup.properties
file.
The example adds one of the component factories shipped with Aria. This factory adds a number of Swing specific components. The registration factory is just another factory and following the above we add another startup property.
Including a Component Factory
NumComponentFactories=1 ComponentFactory0=org.formaria.swing.SwingComponentFactory
Setup the registration factory
First the factory needs to be registered with the main class, this is done through the
startup.properties
file.
Adding the XRegisteredComponentFactory
<code> NumComponentFactories=2 </code> <code> ComponentFactory0=org.formaria.swing.SwingComponentFactory</code> <code> ComponentFactory1=org.formaria.registry.RegisteredComponentFactory</code>
Then, as this class is loaded it attempts to read the XML file detailing the components, this file is also named in the startup.properties file with the "ComponentRegistry" parameters e.g. Specifying the Component Registry
ComponentRegistry=components.xml
The components file then details each component for example:
Using the New Components
<components> <component name="MyComponent" class="myPackage.myClass"> <property name="content" type="get" method="getText"/> <property name="content" type="set" method="setText"/> <Property type="both" name="autoStart"> <Param type="boolean"/> </Property> </component> </components>
You can examine this file after the component registration editor has completed or you could code in manually. The registration can include all the methods available or just those of interest, and when editing an application it may be better to have fewer methods registered as the property sheet will then be more compact. Of course, the methods in the component classes can still be invoked so long as they follow the normal rules for Java beans in declaring getters and setters.
Using reflection
Reflection can be used to find all the component attributes if you don't wish to use the editor tools, or edit the registration XML manually
Taking the automatic registration one step further, it is possible to rely totally on reflection to find the accessor methods of a component. To register components in this way we just add the
reflect="true"
attribute. Thus, for example to register some Swing components we add the following entries to our project's
components.xml
file.
Registering Swing components via reflection.
<Component name="JButton" class="javax.swing.JButton" reflect="true"/> <Component name="JCheckBox" class="javax.swing.JCheckBox" reflect="true"/> <Component name="JColorChooser " class="javax.swing.JColorChooser" reflect="true"/> <Component name="JComboBox" class="javax.swing.JComboBox" reflect="true"/> <Component name="JEditorPane" class="javax.swing.JEditorPane" reflect="true"/> <Component name="JFormattedTextField" class="javax.swing.JFormattedTextField" reflect="true"/> <Component name="JLabel" class="javax.swing.JLabel" reflect="true"/> <Component name="JList" class="javax.swing.JList" reflect="true"/> <Component name="JOptionPane" class="javax.swing.JOptionPane" reflect="true"/> <Component name="JProgressBar" class="javax.swing.JProgressBar" reflect="true"/> <Component name="JRadioButton" class="javax.swing.JRadioButton" reflect="true"/> <Component name="JSlider" class="javax.swing.JSlider" reflect="true"/> <Component name="JSpinner" class="javax.swing.JSpinner" reflect="true"/> <Component name="JSplitPane" class="javax.swing.JSplitPane" reflect="true"/>
In addition to describing the components in this way, the properties of a component can be set reflectively even if the (other) attributes have been specified explicitly. For example If there is no way of setting the attributes of a component directly, or through the
XAttributedComponent
interface, or through a
ComponentAdapter
then reflection will be used to set the properties. The methods signatures are parameter types are set using the JVM type signature syntax, for example
Using reflection to set a component property
<List name="sourceList" x="10" y="11" w="305" h="251" dragEnabled="[Ztrue]"/>
where the
dragEnabled
attribute corresponds to a call to
setDragEnabled( boolean state )
. See http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html for more details of the type specifications.
Using the new components
The components added by the new factory can be used immediately. Each component type should have unique name so when adding a new component all that is necessary is that you know this name. Then the normal Java or XML coding can be used to construct the component.
Jars added automatically to project
When adding components to a page from the Aria palette, jar files are imported to the project lib folder and added to the project properties. For example, the Spinner component utilises the AriaRuntimeCommon jar, this jar is thereby added to the projects lib folder and then added to the libraries in the project properties when the XSpinner component is first added to a Aria page in the project.
Anatomy of a ComponentFactory
Every component factory must implement the ComponentConstructor interface. This interface is relatively simple and is discussed below in the context of the source code for the SwingComponentFactory class.
A Component Factory Implementation
1 package org.formaria.swing; 2 3 import org.formaria.aria.ComponentConstructor; 4 import org.formaria.aria.ComponentFactory; 5 import java.awt.Component; 6 import java.util.Hashtable; 7 8 /** 9 * A factory for non-base Swing components such as Trees 10 * <p>Copyright: Copyright (c) Formaria Ltd., 2001-2004</p> 11 * <p>$Revision: 1.3 $ </p> 12 * License see license.txt 13 */ 14 public class SwingComponentFactory implements XComponentConstructor 16 { 17 private String packageName = "org.formaria.swing"; 18 18 public SwingComponentFactory() 20 { 21 // Register the extra binding factory 22 SwingDataBindingFactory.register(); 23 } 24 25 /** 26 * A generic factory for adding XComponents. The component is constructed, positioned and 27 * added to the parent panel if one exists. The component is named with a counter value 28 * to uniquely identify the control. 29 * This factory does not use this method and all components must be added by name 30 * When a ScrollPane is addd it becomes the parent. 31 * @param cf the calling component factory 32 * @param type a constant identifying the type of component to be created 33 * @param content the component text/content 34 */ 35 public Component constructComponent( XComponentFactory cf, int type, String content ) 36 { 37 return null; 38 } 39 40 /** 41 * A generic factory for adding XComponents. The component is constructed, positioned and 42 * added to the parent panel if one exists. The component is named with a counter value 43 * to uniquely identify the control. 44 * @param cf the calling component factory 45 * @param type a name identifying the type of component to be created 46 * @param content the component text/content 47 */ 48 public Component constructComponent( ComponentFactory cf, String type, String content ) 49 { 50 Component comp = null; 51 52 53 54 if ( type.compareToIgnoreCase( "Tree" ) == 0 ) 55 comp = new Tree(); 56 else if ( type.compareToIgnoreCase( "Table2" ) == 0 ) 57 comp = new Table2(); 58 59 return comp; 60 } 61 62 /** 63 * A generic factory method for adding non component elements. 64 * @param cf the calling component factory 65 * @param type the object type 66 * @param name a name identifying the element to be created 67 * @param content the component text/content 68 * @param attribs the element attributes if any 69 */ 70 public Object addElement( ComponentFactory cf, String type, String name, String content, Hashtable attribs ) 71 { 72 return null; 73 } 74 75 /** 76 * Notify the component factories that some of their settings may have changed. 77 * This factory does not yet use any startup properties or parameters 78 */ 79 public void update() {} 80 81 /** 82 * Set the package name for the factory's widgets. 83 */ 84 public void setPackageName( String defPackage ) 85 { 86 packageName = defPackage; 87 } 88 }
: .
|
Lines 1-15 |
Register/Import individual components |
|
Line 16 |
Names the package. |
|
Lines 18-22 |
Construct a new instance of the factory and sets up the binding factory. The binding factory specifies the bindings that are used by default with the components in this factory. It is not necessary to register the binding types at this point but it is convenient to do so and this helps ensure that the bindings will be available immediately after component construction. |
|
Lines 34-37 |
This is a deprecated API so no implementation is provided. The API was used in the first edition of Aria and proved difficult to extend and was therefore replaced by the API implemented in the next section. |
|
Lines 47-59 |
Does the actual construction of the components. Essentially this factory is a switch on the component type name. This method is called from the component factory whenever its addComponent method is invoked. The factory iterates through the built-in component constructors and then the registered constructors till a component has been constructed for the named type. In this way it is important to name the component types uniquely and to order the factories in the correct order should there be a name conflict. |
|
Lines 69-71 |
This method is not implemented but is required by the interface specification. The interface makes it possible to include non component information in a page description. For example Aria's survey packages allow the response to questions to be specified along with the page. The response element is used by the
The |
|
Lines 83-87 |
This method is used by the component factory and must be provided by all factories. The package name is that of the components rather than the factory itself. |
Using the New Components
<Question name="Q1" x="0" y="100" w="640" h="60" id="1001" content="Is Aria a great Java application framework?" cue="cue.gif"> <Response content="Yes" id="1"/> <Response content="No" id="2"/> <Response content="No comment" id="2"/> </Question>
Sometimes it is useful to register components without first having to create a component factory. Components can be registered by adding entries to an XML file. The
RegisteredComponentFactory
can be used to load components specified in this way.
A sample component
To demonstrate how easy it is to include a new component in Aria we have included the source for a test component in the
Aria Editor
source distribution at
test.Formaria.components.TestShape
. The component doesn't do very much except paint a few trivial shapes. Here's the source code:
TestShape a sample component
package test.Formaria.components; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.JComponent; import org.formaria.aria.AttributedComponent; /** * Draws a simple shape * <p>Copyright: Copyright Formaria Ltd. (c) 2001-2005</p> * <p>License: see license.txt</p> * <p>$Revision: 1.1 $</p> */ public class TestShape extends JComponent implements XAttributedComponent { protected int shape = 0; public static final int RECTANGLE = 0; public static final int ORTHO_LINE = 1; public static final int EXTRABOLD_HORIZONTAL = 2; public static final int BOLD_HORIZONTAL = 3; public static final int NORMAL_HORIZONTAL = 4; public static final int THIN_HORIZONTAL = 5; public static final int EXTRABOLD_VERTICAL = 6; public static final int BOLD_VERTICAL = 7; public static final int NORMAL_VERTICAL = 8; public static final int THIN_VERTICAL = 9; public static final int RIGHT_TOP_LINE = 10; public static final int LEFT_TOP_LINE = 11; public static final int ELLIPSE = 12; public static final int SOLID_ELLIPSE = 13; public static final int SOLID_DIAMOND = 14; public static final int DIAMOND = 15; /** * Constructor for a new Shape */ public TestShape() { } /** * Fills the shape with the background color * @param g the graphics context */ public void paintComponent( Graphics g ) { super.paintComponent( g ); Dimension d = getSize(); g.setColor( getForeground()); switch( shape ) { case RECTANGLE: g.fillRect( 0, 0, d.width, d.height ); break; case ORTHO_LINE: g.fillRect( 0, 0, getSize().width, getSize().height ); break; case EXTRABOLD_HORIZONTAL: g.drawLine( 0, 0 +3, d.width, 3 ); case BOLD_HORIZONTAL: g.drawLine( 0, 0 +2, d.width, 2 ); case NORMAL_HORIZONTAL: g.drawLine( 0, 0 +1, d.width, 1 ); case THIN_HORIZONTAL: g.drawLine( 0, 0, d.width, 0 ); break; case EXTRABOLD_VERTICAL: g.drawLine( 3, 0, 3, d.height ); case BOLD_VERTICAL: g.drawLine( 2, 0, 2, d.height ); case NORMAL_VERTICAL: g.drawLine( 1, 0, 1, d.height ); case THIN_VERTICAL: g.drawLine( 0, 0, 0, d.height ); break; case EXTRABOLD_VERTICAL: g.drawLine( 3, 0, 3, d.height ); case BOLD_VERTICAL: g.drawLine( 2, 0, 2, d.height ); case NORMAL_VERTICAL: g.drawLine( 1, 0, 1, d.height ); case THIN_VERTICAL: g.drawLine( 0, 0, 0, d.height ); break; case RIGHT_TOP_LINE: g.drawLine( d.width, 0, 0, d.height ); break; case LEFT_TOP_LINE: g.drawLine( 0, 0, d.width, d.height ); break; case ELLIPSE: g.drawOval( 0, 0, d.width, d.height ); break; case SOLID_ELLIPSE: g.fillOval( 0, 0, d.width, d.height ); break; case SOLID_DIAMOND: case DIAMOND: { int[] xpts = new int[ 4 ]; int[] ypts = new int[ 4 ]; xpts[ 0 ] = 0 + d.width / 2; xpts[ 1 ] = 0 + d.width; xpts[ 2 ] = 0 + d.width / 2; xpts[ 3 ] = 0; ypts[ 0 ] = 0; ypts[ 1 ] = 0 + d.height / 2; ypts[ 2 ] = 0 + d.height; ypts[ 3 ] = 0 + d.height / 2; if ( shape == SOLID_DIAMOND ) g.fillPolygon( xpts, ypts, 4 ); else g.drawPolygon( xpts, ypts, 4 ); } break; } } /** * Get shape identifier. The ID is an enumerated constant * @param shapeId the new shape ID. */ public void setShape( int shapeId ) { shape = shapeId; repaint(); } /** * Get shape identifier. * @return the enumerated constant for this shape */ public int getShape() { return shape; } /** * Set one or more attributes of the component. Currently this handles the * attributes: * <OL> * <LI>shape, value=1 to 15</LI> * </OL> * @param attribName the attribute name * @param attribValue the attribute value */ public void setAttribute( String attribName, String attribValue ) { if ( attribName.compareTo( "shape" ) == 0 ) shape = new Integer( attribValue ).intValue(); repaint( 100 ); } }
There isn't an awful lot to say about this component as it does so little and the details of the painting are unimportant. What is important though is the interface it offers for programming within Aria.
The component paints a shape which is dictated by the
shape
property. This property has a getter and a setter method (
getShape
and
setShape
).
The component also implements the
XAttributedComponent
method to assist the setting up of the component via XML. The
setAttribute
method required by this interface sets the value of an attribute, in this case the `
shape
' attribute.
If we then build this component into a Jar file for redistribution it can be used within Aria. Using the component registry editor we can add the file and select the Shape property for inclusion. This process generates the following XML:
The XML registration for the test component.
<Components> <Jars> <Jar path="C:\CVS\AriaEditor\dist\TestComponents.jar" project="MyProject"/> </Jars> <Component name="TestShape" class="test.Formaria.components.TestShape" icon="" ui="Swing"> <Property name="Shape" mode="Normal" type="both"> <Param type="int"/> </Property> </Component> </Components>
Special components
Sometimes the component factories may not be enough to allow you handle the needs of an individual component. However, as a Java framework you can employ the normal programming techniques to implement your functionality. This can take you from one line code fragments for setting an esoteric component attribute to complete sets of custom classes. You can freely mix Aria code, Aria XML and normal Java and to illustrate this ability to extend the framework lets look at how to add a web browser component.
Hooking up a web browser
Using the Java.net JDIC project (http://jdic.dev.java.net) we can hook up an instance of the desktop's default web browser. In this example the browser will be embedded in a popup window, an instance of the
Dialog
class and therefore we need to subclass
Dialog
:
Embed a web browser.
package org.formaria.mypackage; import java.net.URL; import java.awt.BorderLayout; import java.awt.Panel; import org.jdesktop.jdic.browser.WebBrowser; import org.formaria.swing.Dialog; import org.formaria.aria.data.BaseModel; import org.formaria.aria.data.Model; import javax.swing.SwingUtilities; import org.jdesktop.jdic.browser.WebBrowserListener; import org.jdesktop.jdic.browser.WebBrowserEvent; import java.net.URLConnection; /** * Show more information about a component * <p>Copyright Formaria Ltd. (c) 2003-2004 </p> * <p>License: see license.txt </p> * $Revision: 1.3 $ not attributable */ public class BrowserDialog extends Dialog implements WebBrowserListener { DataModel selectedNode; int nodeNumber; Dialog webDialog; WebBrowser webBrowser; public BrowserDialog() { } public void pageActivated() { SwingUtilities.invokeLater( new Runnable() { public void run() { website(); } } ); } public void done() { if ( wasMouseClicked() ) { stop(); closeDlg(); } } /** * Show the website */ public void website() { try { // Check if the net is accessible URL url = new URL( "http://www.Formaria.com" ); URLConnection conn = url.openConnection(); if ( conn != null ) { conn.connect(); String websiteUrl = ( String ) getAttribute( "url", "websiteBtn" ); webDialog = new Dialog( false, 0 ); webDialog.setCaption( "Internet content" ); webDialog.setModal( true ); //Use below code to check the status of the navigation process, //or register a listener for the notification events. webBrowser = new WebBrowser(); webBrowser.setDebug( true ); webBrowser.addWebBrowserListener( this ); WebBrowser.Status myStatus = webBrowser.getStatus(); try { webBrowser.setURL( new URL( websiteUrl ) ); } catch ( Exception e ) { System.out.println( e.getMessage() ); return; } Panel panel = new Panel(); panel.setLayout( new BorderLayout() ); panel.setLocation( 0, 0 ); panel.setSize( 700, 500 ); panel.add( webBrowser, BorderLayout.CENTER ); webDialog.setLayout( new BorderLayout() ); webDialog.getContentPane().add( panel, BorderLayout.CENTER ); webDialog.setSize( 700, 500 ); webDialog.doLayout(); webDialog.showDialog( parent ); closeDlg(); } } catch ( Exception ex ) { } } private void stop() { if ( webBrowser != null ) { webBrowser.stop(); webBrowser.setVisible( false ); webBrowser = null; } } // Methods from WebBrowserListener public void downloadStarted(WebBrowserEvent webBrowserEvent) {} public void downloadCompleted(WebBrowserEvent webBrowserEvent) { // webDialog.hide(); } public void downloadProgress(WebBrowserEvent webBrowserEvent) {} public void downloadError(WebBrowserEvent webBrowserEvent) {} public void titleChange(WebBrowserEvent webBrowserEvent) {} public void statusTextChange(WebBrowserEvent webBrowserEvent) {} }
Much of the above code is dictated by the
WebBrowserListener
interface but it is worth noting a couple of points in relation to the code. First the pageActivated method use the
SwingUtilities
invokeLater
method to delay display of the web page as the download of the web content may take considerably longer than displaying the dialog. Secondly the code calls the web browser's
setDebug( true )
method to turn on extra diagnostics. The method causes additional information to be output to the console and this can be quite useful given the number of components involved in the process of displaying the web page and the fact that some of these components are native or operating system components and fall outside of the normal realm of debugging for Java programs.
Using third party components in this way also introduces issues with regard to distribution. While the development environment may allow you to include all the various sub components needed design and build your application yo may need to take some additional steps to ensure that the component can be properly used on end user systems. This additional requirement may simply be to include some additional Jar files or it may be more complex. Unfortunately Aria can do little of this work for you but once you have figured out the requirements it should be possible to include the additional step(s), including the steps necessary to build the distribution files within your project's ANT build file.
Adding a splash screen
The customization of a component is not restricted to creation time and you can continue to interact and customize a component as you would in a typical Java application. To demonstrate this capability we will create an application splash screen that automatically dismisses itself after five seconds. (Please note that as of Version 3.0 with the Swing widget set there is an easier way to create a simple splash screen and this is demonstrated at the end of this chapter).
To display a splash screen for an application the simplest method is to invoke the display of a popup dialog in your application's first page. The process requires a small amount of Java coding. The display code can be embedded in the first page's
pageActivated
method as below:
Launch a splash screen
private static boolean splashActivated = false; public void pageActivated() { // This flag prevents the splash screen being redisplayed if the first page is reactivated // or shown again. if ( !splashActivated ) { showVersionInfoDialog( true ); splashActivated = true; } } private Dialog showVersionInfoDialog( boolean modal ) { final Dialog popupDialog = (Dialog)pageMgr.loadPage( "SplashScreen" ); final Page thisPage = this; final boolean isModal = modal; SwingUtilities.invokeLater( new Runnable() { public void run() { // Only needed if the content contains bound controls. popupDialog.updateBindings(); popupDialog.setModal( isModal ); // Force the dialog to calculate its size popupDialog.pack(); popupDialog.setSaveOnClose( false ); // Sleep for 5 seconds and then close the dialog - only for the `modeless' version. // Change or remove the next if statement if you want a model splash screen. // to be dismissed on the timer if ( !isModal ) { new Thread() { public void run() { long startTime = new Date().getTime(); try { // Loop so that the dialog can repaint itself once any images have loaded while (( new Date().getTime() - startTime ) < 5000L ) { popupDialog.repaint(); Thread.currentThread().sleep( 100 ); } } catch ( Exception ex ) {} popupDialog.closeDlg(); } }.start(); } popupDialog.showDialog( thisPage, "Welcome to my application", null ); } } ); return popupDialog; }
The
showVersionInfoDialog
method loads the
SplashScreen
page (it can be setup like any other dialog/page) and then starts a background thread that will dismiss the dialog after a sleep period of 5000 milliseconds.
Finally in implementing the actual splash screen it is important to note that the page being displayed is assumed to be an instance of
Dialog
and as such it needs to derived from the
Dialog
class instead of
Page
. If you are using XML don't forget to specify the class in the page declaration as follows:
Specify the Dialog class for your splash screen in XML
<Page class="org.formaria.swing.Dialog">
Like in the case of the web browser the interesting code embedded in a call to
invokeLater
.
Dropping to Java can help work around many limitations and solve many more problems than the above examples. In fact you should be able to employ just about any type of component or component feature within your Aria application. And remember, where XML is insufficient you can supplement it with Java.
Swing splash screen
In the Swing version of the Aria libraries there is a class
XSplashWindow
that can be used to display a simple splash screen. The splash window is loaded prior to the rest of the Aria framework being loaded and therefore not all the resource handling of the framework is available to this class. In fact the class loads and then invoked the main method in the framework proper as we will see below. The sequence of execution is thus, that firstly the
SplashWindow
class is invoked and it in turn starts the class passed as an argument (or
Applet
if none is specified), which should be the entry point to the Aria framework (which, of course depending on the application style being used).
The the application is invoked as follows:
Starting with a splash screen
java -cp ./lib/AriaRuntimeCommon.jar org.formaria.swing.splash.SplashWindow <arglist>
where
is the argument list that would otherwise be passed to the
Applet
, or whatever was the normal startup class for your application. The application also needs to find the file
splash.gif
, which should be located on the classpath. The splash screen functionality can be found in a number of the examples that ship with Aria. The splash screen functionality is also setup by the project wizard, by choosing the
The results really depend on what you add as the splash image. The splash screen can also be customized by subclassing the SplashWindow class, and in the image below this has been done to add transparency support
Component customization
Aria 3.0 adds a new facility for customizing components such that a collection of method calls can be made to customize a component and set properties on that component. The facility is itself customizable, supporting adapters to control how the properties are applied to the component. The customizations can be applied post creation of the component or just before activation of the page, when the component has been populated.
For example in the case of a table the property may apply to the table columns rather than the table itself. In the example below a table is customized in this way:
Setting atable customizer
<ScrollPane> <Table2 name="currentAED" .... customizer="tableCustomizer"/> </ScrollPane>
the
customizer
attribute refers to a customization specified in the
customizations.xml
file. The customization file is as follows:
A sample table customization
<customizer> <Adaptors> <Adaptor name="ColumnAdaptor" class="org.formaria.registry.TableColumnCustomizer"/> </Adaptors> <PropertySets> <PropertySet name="tableCustomizer" when="1"> <AutoCreateColumnsFromModel args="false"/> <GridColor args="white"/> <ViewportBackground args="white"/> <Background target="parent" value="white"/> <HeaderRenderer adaptor="ColumnAdaptor" scope="*" class="org.formaria.swing.table.TableHeaderRenderer" args="getTableHeader()"/> <CellRenderer adaptor="ColumnAdaptor" scope="0-6" class="org.formaria.swing.table.AltRowTableCellRenderer"> <VerticalAlignment args="1"/><!--SwingConstants.TOP --> <AltUnselectedColors args="0,0,102;252,252,255"/> </CellRenderer> <CellRenderer adaptor="ColumnAdaptor" scope="N" class="org.formaria.swing.table.AltRowTableCellRenderer"> <VerticalAlignment args="1"/><!--SwingConstants.TOP --> <AltUnselectedColors args="0,0,102;252,252,255"/> <WrapsText args="true"/> </CellRenderer> <AutoResizeMode args="1"/><!--JTable.AUTO_RESIZE_NEXT_COLUMN --> </PropertySet> </PropertySets> </customizer>
The result of the above customization is a table like the following with row striping and customized headers:
Using Drag and Drop
Drag and drop supported has been added for selected Swing components. Support is enabled by adding
dragEnabled="true"
as an attribute. Additional support can be registered by adding a
transferhandlers.xml
file to the project. The setup is similar to that of the setup of data bindings.
Drag and drop configuration
<Bindings> <InspectorTransferHandlers> </InspectorTransferHandlers> <ClassTransferHandlers> <TransferHandler target="org.formaria.swing.List" class="org.formaria.swing.dnd.ModelTransferHandler" type=""/> </ClassTransferHandlers> <InterfaceTransferHandlers> <!-- This does not actually use a binding --> <!--TransferHandler target="org.formaria.aria.ModelHolder"> <onError fixError="DataSourceClassMissing"/> </Binding--> </InterfaceTransferHandlers> <InstanceTransferHandlers> <TransferHandler target="org.formaria.swing.Image" class="org.formaria.swing.dnd.ModelTransferHandler" type=""/> </InstanceTransferHandlers> </Bindings>
- Printer-friendly version
- Login or register to post comments