Shayne R Flint [HREF1], Department of Computer Science [HREF2] , Australian National University [HREF3], ACT, 0200. shayne@cs.anu.edu.au
Clive V Boughton [HREF4], Department of Computer Science [HREF2] , Australian National University [HREF3], ACT, 0200. clive@cs.anu.edu.au
The World Wide Web is increasingly being used, across all sectors of the Information Technology industry, to host distributed interactive applications. Many of these applications are built using a combination of different, and sometimes inappropriate, technologies. Often the final products are complex, and the associated likelihood of increased development, integration, deployment and maintenance problems lead to high overall lifecycle costs.
This paper outlines the requirements, design, implementation and testing of armidale, a set of open source programs and libraries designed to radically simplify the development, deployment and use of web applications that have rich graphical user interfaces. Armidale applications are developed, using conventional programming techniques and the armidale API, as if they were stand-alone programs. These programs can then be run on stand-alone computers or on an armidale server. When running on a server, armidale applications display their GUI on client computers across the internet (or intranet). A high level, light weight message protocol between the server and its clients ensures that armidale applications respond well to user interaction.
The work reported in this paper is part of a larger research effort to develop a technique which aims to increase the likelihood that decisions made throughout, and at all levels of, an organisation contribute in a coordinated way to satisfying the organisation's requirements and those of its stakeholders (Flint 2001). The approach, called Capability Dynamics, is based on the use of Capability Dynamics Models (Flint 1999) which are developed and maintained by the organisation to provide decision-makers with an organisation wide, shared and evolving understanding of the systems comprising the organisation and its environment, how the capabilities of these systems interact to satisfy stakeholder requirements, and how all these things are likely to evolve with time and in response to change.
The development of these Capability Dynamics Models is likely to require significant effort. In addition, the authors believe that a sense of ownership in their development and use will be important to the success of Capability Dynamics. It was therefore proposed (Flint 2001) that Capability Dynamics Models be developed by collaboration amongst all stakeholders within an organisation, as well as researchers and consultants.
In order to support the collaborative development of Capability Dynamics Models, the authors are developing a computer based Distributed Capability Dynamics Modeling Tool which is intended for day-to-day use throughout and at all levels of an organisation. The tool has been designed to allow everyone within an organisation to capture their own view of those systems with which they interact or are a part, and to run agent based simulations to describe the way in which capability develops over time, and in response to actual, proposed and planned changes. In addition, the proposed tool will provide facilities that allow stakeholders to discuss differences in opinion, identify those differences that are important and, if required, resolve them.
It is hoped that this collaborative approach, supported by computer based tools, will result in the emergence of Capability Dynamics Models for entire organisations formed from the knowledge and individual contributions of their people.
The distributed and collaborative nature of the tool support discussed above suggests that a web based implementation of the Distributed Capability Dynamics Modeling Tool would be appropriate. This provided the motivation that led the authors to look at current web application development approaches and to then develop armidale.
Popular approaches to the development of web applications use various combinations of well established technologies including HTTP, HTML, client side scripts such as JavaScript [HREF5] and server side scripts such as PHP [HREF6]. It is also common to use server side technologies such as JSP [HREF7] and ASP [HREF8] to generate HTML and client side scripts on-the-fly in response to HTTP requests from clients.
More recently, a number of newer technologies have emerged, including XUL [HREF9], which aims to simplify the development of client side GUIs, and .NET [HREF10] which supports the development of web services using SOAP [HREF11]. As is often the case, these technologies build upon the growing mountain of HTTP, HTML and scripting technologies described above.
In order to develop effective web applications, developers need to master many of the above technologies within the context of individual projects. In addition, developers need to deal with complex issues of compatibility between different versions of the technologies, and in particular, the compatibility of different web browsers with the various scripting languages and variations of HTML used throughout the internet. To a lessor extent, some of these issues also need to be understood by end users.
The authors believe that the need to master this ever-increasing set of technologies and their interaction is likely to increase development, integration, deployment and maintenance problems associated with the life cycle of web applications. In addition, the authors find it strange that the use of such inherently complex and poorly engineered approaches is rarely questioned and that 'new' ideas and approaches often add even more complexity to what appears to be an unsustainable foundation for the development of increasingly complex web applications.
In light of the above issues, the authors believe that development of the Distributed Capability Dynamics Modeling Tool could benefit from a radically simplified web application development approach. The only real ongoing efforts to offer such an approach are those by Bullant [HREF12] and Droplets [HREF17]. Bullant is an Australian company that has developed a set of proprietary technologies which enable the development of sophisticated and highly scalable web applications by eliminating what they call the 'infrastructure zoo' of HTML and associated add-ons. The Droplets technology, which was recently introduced to the authors, is another commercial web application development technology that eliminates the use of HTML and associated web technologies.
Because of their commercial nature, Bullant and Droplets are unattractive to our ongoing Capability Dynamics research. This view has strongly influenced the design, implementation and testing of the open source armidale system described in the remainder of this paper. It is hoped that other projects can also make use of the armidale technology.
Initial requirements for armidale emerged from the wider research discussed above and evolved in an iterative fashion as the system has been developed and used. While additional requirements are likely to emerge during the open source development process proposed for the future, the requirements, as they were at the time of writing, are outlined below along with details of the design approaches used to satisfy them.
Armidale shall provide a simple programming model to support the development of interactive applications that are able to run on stand-alone computers or on a server. When running on stand-alone computers, application GUIs shall be displayed on the host computer. Armidale applications installed on a server shall be started by clients connected to the server via the internet or an intranet. In this mode of operation, application GUIs shall be displayed on the connected client computer.
The development of armidale applications does not involve the use of HTTP, HTML or scripting languages of any kind. Instead, armidale applications are written in Java, using conventional programming techniques and the armidale API, as if they were stand-alone programs running in isolation from the internet. That is, the armidale API abstracts the complexities of the internet and platform dependencies away from the concerns of developers as depicted in Figure 1.
Developers using armidale need only learn one programming language (Java), and a simple user interface API. There is no need to learn and become experienced in multiple Web technologies such as HTML, PHP and JavaScript etc. There is no need to understand the way in which these technologies interact and perform on various platforms and in various combinations of versions.
Figure 1: The armidale conceptual design
When an armidale application is started, it is given a context. This context is used by armidale API factories (Gamma 1995) to determine which implementation of the API should be used for the current execution environment. When an application is started within a platform (stand-alone) context, the factories will return implementations that use a platform API such as Java Swing [HREF13] to create and manipulate GUI objects on the host computer.
When an application is started within a client-server context, the factories will return implementations that communicate with connected clients via the Open Binary Message Protocol (OBMP) described elsewhere in this paper. On the client, platform context implementations are used to display GUI objects so that applications running in a client-server context have the same look and feel as they have when running in a stand-alone context.
Appendix A provides more details on the operation of armidale applications in stand-alone and client-server contexts.
Application developers shall be able to use armidale to create interactive applications with rich Graphical User Interfaces (GUIs) comprising elements such as buttons, images, lists, tree views, tables etc. Such applications shall have the same look and feel as conventional applications available on user computers.
The armidale API provides mechanisms to create and manipulate the GUI objects listed in Appendix B. In general, the behavior of these objects follows that of corresponding Swing widgets [HREF13].
Platform context implementations of the armidale API make use of platform specific APIs such as Java Swing. The look and feel of GUI objects, is therefore similar to that of applications native to the host platform. Because Platform Context implementations are also used to display GUIs on clients connected to armidale applications running on servers, the look and feel of armidale applications is independent of where the application is actually running.
Figure 2 shows a number of armidale test applications running on a KDE desktop. The applications shown could be running locally or on remote servers over the internet as it makes no difference to their look and feel on the desktop.
Figure 2: Some armidale applications running on a KDE desktop
Users shall be able to start armidale applications in the same way as native applications available on the user's computer. In addition, users shall be able to start an armidale application from a launcher by entering its URL or by referring to a list of bookmarked applications.
Armidale applications, whether installed locally or on remote servers, can be started using any of following methods, all of which create an appropriate context (local platform or server) and then run the application within that context. As far as the user is concerned, armidale applications start, look and feel like any other application. The user receives no visible indication of where applications are actually running.
Figure 3: The armidale launcher
Armidale applications shall be capable of running stand-alone and as server applications on computers running Linux (Intel), Solaris (Sparc), Mac OS X (Power PC) and Windows 2000 (Intel).
The armidale system has been written in standard Java 2 using the Sun Microsystems JDK 1.4.0 (standard edition) and has been designed to run on any JDK 1.3 or later platform. Successful testing has been conducted on Linux (SuSE and RedHat), Solaris 8, Mac OS X and Windows 2000.
Armidale shall not restrict the use, by application developers, of third party technologies such as SQL databases and the SWARM agent based simulation system [HREF15].
Armidale applications are developed using standard Java and as such can make use of any available Java API. This includes the JDBC API which can be used to access SQL databases, and the Swarm Java API. The only exception is that user interface APIs such as AWT and Swing should not be used because armidale provides its own user interface API which makes it possible to run armidale applications locally or over the internet or an intranet.
Armidale application developers shall be able to add new GUI objects to the armidale system. The implementation of this requirement shall ensure that objects added by one developer are uniquely identified and that they do not interfere with objects created by other developers.
The standard armidale API includes mechanisms to create and manipulate many standard GUI objects such as buttons, lists, tables and icons etc. Each of these GUI objects are implemented by a number Java classes and interfaces. For example the PushButton object is implemented by the following Java interface and classes:
interface armidale.api.gui.PushButton
class armidale.api.gui.PushButtonFactory
class armidale.api.gui.impl.clientserver.PushButtonClientImpl
class armidale.api.gui.impl.clientserver.PushButtonServerImpl
class armidale.api.gui.impl.platform.<PLATFORM>.PushButtonImpl
(where PLATFORM is a platform name such as swing)
All of these interfaces and classes, with the exception of the platform implementation classes such as armidale.api.gui.impl.platform.swing.PushButtonImpl, are completely generated by the armidale.utilities.makeclass.Main program based on specifications provided in XML files as depicted in Figure 4. An example of an XML GUI object specification is provided at Appendix D to this paper.
Figure 4: Generation of GUI element source code
The platform implementation classes for each GUI object, such as armidale.api.gui.impl.platform.swing.PushButtonImpl, are generated by the armidale.utilities.makeclass.Main program with empty method bodies. It is up to the GUI object developer to implement the bodies of these methods (e.g. the swing implementation of the object). This often involves no more than making simple calls to platform objects such as those provided by Swing.
An important feature of armidale is that the above process can be used by application developers to add new GUI Objects to the system. All that is required is an XML specification of the new GUI object and implementations of the platform specific methods described above. Once a new GUI object has been developed, it can be installed on the client and server computers by copying its class files, or a JAR file containing the class files, to a directory on the user's Java class path. The new GUI objects can then be used by application developers in the same way as the standard objects provided in the armidale distribution.
Note that the armidale API provides a mechanism for applications to check that any non-standard GUI objects required by the application are correctly installed on a client computer before the application starts (see the description at Appendix A). In addition, all GUI objects have a unique Class ID. These Class IDs are 32 bit numbers and will be allocated by the authors in blocks of 100 to interested developers.
The design of armidale shall make provision for the use of devices such as mobile phones and PDAs as armidale clients.
The armidale.utilities.makeclass.Main program described above is able to generate platform implementation classes (with empty method bodies) for any number of client platforms. At present, only the Swing platform has been fully implemented, but all of the infrastructure is in place to implement other platforms such as Espial [HREF16]. Once a platform API has been implemented for a new device such as a phone or PDA, the armidale application launcher can be used on the new device to start armidale applications running on armidale servers.
The armidale system shall minimise the use of network bandwidth. An important motivation for this requirement is that devices such as phones and PDAs may, in future, be used as armidale clients connected to servers via low bandwidth wireless links.
The design of armidale makes use of the following techniques to minimise the use of network bandwidth.
The armidale system uses TCP/IP to pass messages between clients and servers. In order to minimise bandwidth usage, armidale messages use a simple binary format called the Open Binary Message Protocol (OBMP). Each OBMP message comprises a 32 bit message length and a set of data items including primitive type values such as int, byte, float, double etc., and more complex types like String, Color and Font. Armidale includes an API for constructing and interpreting OBMP messages.
Apart from the minimal use of bandwidth, there are two other reasons for choosing a binary protocol rather than one of the more popular XML protocols such as SOAP [HREF11]. Firstly, our messages are abstracted away from any programmer or user involvement because they are created, transmitted and interpreted in code generated by the armidale.utilities.makeclass.Main program from high level specifications. So the only real requirements on the message protocol are that it be able to transmit the required information and that it be as efficient as possible.
Secondly, despite a common belief to the contrary, XML is nothing more than a human readable format for describing data. If data contained in any kind of message is to be of value, the same meaning must be attached to it by its creator and interpreter. This applies to XML messages as much as it does to any other form of message including binary. XML does not magically add meaning to messages and does not change the fundamentals of communications. So, because armidale messages are unlikely ever to be created or read by humans there is little reason to use XML.
When an application creates an Image object it initially has no associated image data and is displayed as a "broken" picture icon. The application can then set the image data by calling the setImageData() or setFile() methods.
When the setImageData() method is called, image data is passed as a parameter and used to create a platform specific image. The implication of this is that in a client-server context, the image data is sent over the network each time the setImageData() method is called.
A more efficient approach is to use the setFile() method which takes the name of a file in the armidale filesystem. This filesystem is simply a directory within the user's home directory called .armidale/filesystem and is created during the installation process.
When the setFile() method is used in a stand-alone context, the contents of the file are used to create a platform specific image. In a client-server context, the name of the file and its date-time stamp are sent to the client. When the client receives the message, it attempts to open a file with the same name in its local armidale filesystem. If the file exists on the client and has the same date-time stamp, a platform specific image is created from the contents of the local file. If the required file does not exist in the client's filesystem, or the date-time stamp is incorrect, then the client will request a copy of the file from the server. The server will then send the file to the client, and it will be saved on the client's armidale filesystem. The contents of the file are then used to create a platform specific image.
The above approach implements a simple, but effective image cache and can be applied to other media types in future.
Armidale is able to efficiently display information from very large data structures or models in GUI lists and tables on the client. The technique ensures that only those items that are visible and are needed for smooth scrolling of lists and tables are passed from the server to the client. As a list or table is scrolled by the user, items that are not yet available on the client are displayed as "please wait...". When the user stops scrolling a request is sent to the server for any items that need to be displayed. When the items arrive at the client the "please wait..." messages are replaced with the real data.
Armidale shall be developed as an open source project.
Early versions of armidale were designed and implemented by the authors with the view of making the project open source. The entire system was developed using technologies that would allow armidale to become an open source project.
Armidale has since been released as an open source project. The project is hosted by Source Forge [HREF18], a web site that provides a suite of tools which coordinate the development, distribution, maintenance and use of open source projects, including file transfer services, problem reporting and tracking, support request tracking, and discussion forums etc.
It is hoped that this open source approach will encourage wider use of Armidale as well as its continued development and support.
The implementation of armidale has been uneventful. The tools used included SuSE Linux [HREF19], the Sun Microsystems Java Development Kit Standard Edition (version 1.3 and 1.4) [HREF20], the Apache Ant java build tool [HREF21], the JEdit integrated development environment [HREF22] and various Linux tools such as xfig and Gimp. There were no project delays caused by limitations or problems with the tools used.
Functionality of the armidale system was tested using two test applications. The first, SimpleApp, was intended only to test the basic armidale infrastructure. This covered the armidale API architecture, the armidale application launcher, the ability to run applications in different contexts, and the ability to manipulate GUI objects and to process their events correctly. The annotated source code for SimpleApp is at Appendix C to this paper.
The second test application, GuiTest, was designed to test each of the armidale GUI objects. As GUI objects were implemented, they were added to this test application and as more are developed in the future, they too will be added to GuiTest. A design feature of GuiTest is that individual GUI object tests are implemented in separate classes which can be executed in isolation from the main GuiTest application.
The screen shot depicted in Figure 1 shows the SimpleApp and GuiTest applications along with a number of individual widget test programs.
Table 1 shows the platforms, operating systems and Java versions on which the above applications were tested. While Java 1.4 is the preferred platform, armidale should run on any Java 1.3 or 1.4 platform.
| Hardware | OS | OS Version | Java version |
| Intel PC | Linux | SuSE 7.3 | 1.3, 1.4 |
| Intel PC | Linux | RedHat 7.2 | 1.3, 1.4 |
| Sun Sparc | Solaris | 8 | 1.3 |
| Macintosh G4 Titanium Notebook | MacOS X | 10.1.3 | 1.3 |
| Intel PC | Windows | 2000 | 1.3, 1.4 |
While the design and conduct of credible software engineering experimentation is considered important (Fenton 1994), none has been conducted to test the view that armidale simplifies web application development. Such experimentation was beyond the scope and resources of the armidale project at the time of writing.
Nonetheless, a number of characteristics support the view that armidale simplifies the development and use of web applications. The most important of these is the way in which all aspects of the internet, hardware platform, and operating system are abstracted away from both the application developer and user. When using more traditional web application development approaches, the developer will usually deal concurrently with low level details of the internet including HTML, an array of client side and server side scripting languages, browsers and the many compatibility issues that go with them. Likewise, users of traditional web applications also need to deal with a wide range of compatibility issues and limited capabilities of the web browser model. All of these issues are completely irrelevant to the developer and user of armidale applications, or are abstracted away from the developer behind the armidale API. When we also consider the use of a single traditional object oriented programming language, and the ease with which armidale can be extended, the claim that armidale enables simplified development of web applications would appear reasonably sound.
From a qualitative perspective, the authors experience in developing demonstration and test programs would also support the view that armidale does indeed simplify the whole process of developing, testing, deploying and using web applications. The authors believe that the reader will develop a similar view by walking-through the sample application code at Appendix C, installing the armidale development system available from Source Forge [HREF18] and going through the process of compiling, deploying and using the various demonstration programs included in the distribution.
The armidale system can be downloaded, under the terms of a BSD open source license, from a web site at http://sourceforge.net/projects/armidale [HREF18]. This web site also provides supporting documentation.
For testing purposes an armidale server and the test applications described above are usually running at http://armidale.anu.edu.au [HREF14].
While armidale is now ready to support the author's Capability Dynamics research, the following tasks were planned or underway at the time of writing to further its development and use.
A longer term task, may be the development of new platform support for mobile devices.
This paper has described the requirements, design and implementation of software used to develop interactive internet based applications in support of wider research being undertaken by the authors. Because the resulting software appears to have wide general purpose applicability, it has been released to the public as an open source project in the hope that others may find it useful and that it may be enhanced and matured by a group of interested open source developers.
Fenton, N. et al. (1994), Science and Substance: A Challenge to Software Engineers, IEEE Software, July 1994.
Flint S. R. (1999), A model which helps control change in dynamically complex purposeful systems", Proceedings of the 1999 Systems Engineering Test and Evaluation conference, Adelaide South Australia, October 1999.
Flint S. R. (2001), Capability Dynamics - An Approach to Capability Planning in Large Organisations, Proceedings of the 2001 International Council on Systems Engineering Symposium, Melbourne, Australia, July 2001.
Gamma, E. et al. (1995), Design Patterns, Elements of Reusable Object-Oriented Software, Addison-Wesley, Reading, MA, USA. ISBN 0-201-63361-2
Armidale applications are based on Java classes that extend the armidale.api.Application class and provide an implementation for the inherited init() method. This init() method is effectively the "main" method of an armidale application. User interfaces are created programmatically using the armidale.api.gui.* API. This API provides a set of GUI object factories (Gamma 1995) that create instances of classes which implement specific GUI object interfaces. For example, the armidale.api.gui.PushButtonFactory creates instances of classes that implement the armidale.api.gui.PushButton interface.
When an armidale application is started, it is given a context. This context is used by the armidale API factories to determine which implementation of the API should be used for the current execution environment. When an application is started within a platform context, the factories will return implementations that use a platform API such as Java Swing [HREF13] to create and manipulate GUI elements on the host computer. When an application is started within a server context, the factories will return implementations that communicate with connected clients via the Open Binary Message Protocol (OBMP) described elsewhere in this paper. On the client, platform context implementations of GUI objects are used so that applications running in a client-server context have the same look and feel they have when running in a stand-alone context.
The following sections provide more detail about the operation of armidale applications in stand-alone and client-server contexts. The information provided is best read in conjunction with the annotated source code for the SimpleApp test program at Appendix C.
If an armidale application is started in a stand-alone environment (i.e. no internet or intranet involved) a Platform Context such as SwingContext will be created and used as depicted in Figure 5 (also refer to the main() method in the sample code at Appendix C). This context will cause the armidale API factories to use Platform Implementations of the API to create objects that translate armidale API method calls directly into corresponding calls to a Platform API (e.g. Swing) thus causing the GUI of the application to be displayed on the stand-alone device.
Figure 5: An armidale application running in a stand-alone context
The following paragraphs and the block diagram at Figure 6 describe how armidale applications run in the server context. More details, along with the source code for armidale can be found at Source Forge [HREF18].
Figure 6:An armidale application running in a client-server context
The armidale server (armidale.api.Server) is a very simple Java program. It listens on a specified port for TCP/IP connections from clients. All clients, including the armidale application launcher, make use of the armidale.api.RemoteApplication class to start applications on remote armidale servers. This class is instantiated with the URL of a remote application and any required arguments. When an instance of this class is created, it sends a CONNECT message to the server containing the name of the application the client wants to run and a list of arguments. This application name is in fact the name of a Java class that extends armidale.api.Application, is installed on the server computer, and is visible to the armidale server (i.e. on its class path).
When a server receives a CONNECT message from a client, it creates a Server Context containing a Server Transport connected to the requesting client. This context is then used to create an instance of the requested application class. If everything is OK, a CLASS_INFORMATION message is sent back to the client specifying any special requirements the application may have (such as non-standard widgets). If a problem occurs on the server (such as a missing application class), an ERROR message is returned to the client.
When the client receives the CLASS_INFORMATION message it checks that it is able to satisfy the needs of the remote application (e.g. availability of any special widgets). If all is well, the client will send a CLIENT_OK message to the server and will create a Client Context containing a Platform Context (used to display the GUI on the client) and a Client Transport which waits for and process messages from the connected server.
When the server receives the CLIENT_OK message, it calls the start() method of the requested application instance (which is a Java Thread). When the application is started, the init() method is called. The init() method, defined by the application developer, will usually create a user interface (which will be displayed on the client) and set up callbacks. The application's Server Transport will then wait for and processes EVENT messages from the client.
When an application creates a new GUI object such as a PushButton (using the PushButtonFactory), the server implementation of the object sends a CONSTRUCT message to the client. When the client receives this message it uses the applicable factory to create a instance of the required class within the Client Context. These client implementations contain an associated implementation of the Gui object class within a Platform Context such as Swing. These Platform Context objects display the GUI widgets on the client device.
When an application modifies an attribute of a GUI object, such as the title of a PushButton, the server implementation of the object sends a SET_ATTRIBUTE message to the client. When the client transport receives this message, it dispatches it to the applicable client implementation which in turn calls the appropriate methods in the associated platform implementation.
Many of the GUI objects supported by armidale are capable of generating events. PushButtons, for example, are able to generate ACTION events. Events are handled in armidale by callbacks which are implementations of callback interfaces that define methods called when an event is generated by a GUI object. These callback interfaces are implemented by the application programmer to define the required response to events. Instances of these classes are registered with the GUI Object of concern.
When a client event occurs (e.g. the user clicks a PushButton), an EVENT message is sent to the server via the Client Transport. When the corresponding Server Transport receives an EVENT message it is dispatched to the subject object which in turn calls the applicable method of each callback registered with it.
Event messages are only sent from the client to the server if one or more callbacks are registered with the subject GUI object.
Image
VisibleObject
Component
MenuBar
PopupMenu
Widget
Action
Button
MenuItem
CheckBoxMenuItem
Menu
PushButton
Toggle
CheckBox
RadioButton
Label
Desktop
LabeledWidget
Slider
Panel
BorderPanel
BoxPanel
FlowPanel
GridPanel
RadioButtonPanel
ListBox
ComboBox
ProgressBar
Table
ScrollPanel
SplitPanel
TabbedPanel
Text
TextField
PasswordField
TextBox
Tree
Window
Frame
InternalFrame
BorderPanelWidget
GridPanelWidget
TabbedPanelWidget
1:/* 2: * Copyright (c) 2000-2002, Shayne R Flint 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms, with or without 6: * modification, are permitted provided that the following conditions 7: * are met: 8: * 9: * 1. Redistributions of source code must retain the above copyright 10: * notice, this list of conditions and the following disclaimer. 11: * 12: * 2. Redistributions in binary form must reproduce the above copyright 13: * notice, this list of conditions and the following disclaimer in the 14: * documentation and/or other materials provided with the distribution. 15: * 16: * 3. The name of the author may not be used to endorse or promote products 17: * derived from this software without specific prior written permission. 18: * 19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29: */ 30: 31:package armidale.test; 32: 33:import armidale.api.Application; 34:import armidale.api.ClassInformation; 35:import armidale.api.ProductInfo; 36:import armidale.api.context.*; 37:import armidale.api.context.clientserver.*; 38:import armidale.api.context.platform.*; 39: 40:import armidale.api.gui.*; 41:import armidale.api.gui.constants.*; 42:import armidale.api.io.Debug; 43:import armidale.api.io.File; 44: 45:import java.io.IOException; 46: 47:// This is a simple armidale application which will open a small frame 48:// with an image and button on it. A callback is defined to display 49:// a message on the server when the button is clicked.
Figure 7: SimpleApp screen shot
50:// 51:// Because this is an armidale application, it can be run stand-alone or 52:// over a network using the armidale launcher. 53:// 54: 55: 56:// All armidale applications must extend armidale.api.Application or an 57:// extension of it. 58:// 59:public class SimpleApp extends Application { 60: 61: 62: public void init() { 63: 64: // This is where the main work is done. The init() method is declared 65: // in armidale.api.Application and is called as part of the application 66: // execution (see the armidale.api.Application.run() method). 67: // 68: 69: // We start by creating a frame using the armidale.api.gui.FrameFactory. 70: // This factory creates implementations of the armidale.api.gui.Frame 71: // interface based on the specified context (usually server or local 72: // swing). The context parameter used below is declared in 73: // armidale.api.Application (our parent class) and is set by the 74: // environment starting the application. In the standalone case this 75: // is set in a main method like the one defined later in this class. 76: // In the case of a server environment, it is set by the armidale server 77: // in response to a connection request from a client. 78: // 79: // The main point here is that the application developer doesn't have to 80: // worry about what context is set to. He just passes it as a parameter 81: // the the various factories and other API methods. 82: // 83: Frame frame = FrameFactory.create(context); 84: 85: 86: // Armidale handles events using a callback mechanism. When an event is 87: // generated by a widget (eg. a user clicks a button) a specific method 88: // of each associated callback object is called. For example, when a Frame 89: // is closed, a frame close event is generated. This event results in a 90: // call to the windowClosing() method of each associate WindowCallback 91: // object. 92: // 93: // In the following statement we add a callback to the frame to handle 94: // window close events (ie. when the user clicks the close icon at the top 95: // of the window). As a convenience, armidale includes a simple class 96: // (armidale.api.gui.WindowCloseCallback) that implements various options 97: // regarding the closing of frames. Here we have chosen to stop the 98: // application when the user closes the frame. 99: // 100: frame.addWindowCallback 101: ( new WindowCloseCallback 102: (context, WindowCloseCallback.STOP_APPLICATION_ON_CLOSE)); 103: 104: 105: // Complete the initialization of the frame by setting its title, size etc. 106: // 107: frame.setTitle("Simple Application"); 108: frame.setSize(new Size(420, 300)); 109: frame.setAlignment(Frame.CENTER); 110: frame.setResizable(false); 111: 112: 113: // The image and button will be displayed on a BorderPanel. Create the 114: // main panel and set its background color. Note that the Color class here 115: // is an armidale.api.gui.Color, not a java.awt.Color 116: // 117: BorderPanel mainPanel = BorderPanelFactory.create(context); 118: mainPanel.setBackgroundColor(Color.WHITE); 119: 120: 121: // Create the image and set the image data to the contents of a specified 122: // file. 123: // 124: // By using the setFile() method to set the image data, this application, 125: // when run on a server, will ask the client to try and load the image 126: // from the client filesystem. If the image is not available on the client, 127: // it will downloaded from the server. 128: // 129: Image image = ImageFactory.create(context); 130: image.setFile(new File("images/armidaledemo.png")); 131: 132: 133: // Create a label, based on the above image and set its alignment 134: // 135: Label label = LabelFactory.create(context); 136: label.setImage(image); 137: label.setAlignment(Label.CENTER); 138: label.setText( 139: "<html><body><center>" 140: + "<font color=\"black\">Thank you for using <font color=\"purple\">" 141: + "armidale</font>.<br><br>" 142: + "If you have any comments, suggestions or problems, please " 143: + "email the author at <font color=\"blue\">shayne@cs.anu.edu.au</font>" 144: + "or register a comment at" 145: + "<font color=\"blue\">http://sourceforge.net/projects/armidale.</font>" 146: + "</font></center></body></html>" 147: ); 148: label.setTextPosition(Label.NORTH); 149: 150: 151: // Add the label created above to the main panel. To add a widget to a 152: // border panel, it needs to be wrapped up in a BorderPanelWidget along 153: // with its position (constraints) on the border panel (ie. north, south, 154: // east, west or center). Note that this pattern is used for many of the 155: // armidale panels (eg. GridPanel and GridPanelWidget). 156: // 157: mainPanel.addWidget 158: ( BorderPanelWidgetFactory.create 159: (context, label, BorderPanelWidget.CENTER)); 160: 161: 162: // Following the same pattern of widget creation, we now create a button 163: // and set some its properties 164: // 165: PushButton testButton = PushButtonFactory.create(context); 166: testButton.setText("Test Events"); 167: testButton.setPreferredSize(new Size(150, 25)); 168: 169: 170: // For convenience, armidale provides a Debug implementation of all 171: // callback classes. These Debug classes print details of events generated 172: // by associated widgets. 173: // 174: // In the following code we add to the button a pre-built 175: // ActionCallbackDebug object which displays a debug message when the 176: // button is pressed. 177: // 178: testButton.addActionCallback(new ActionCallbackDebug(context)); 179: 180: 181: // We are now going to create a FlowPanel on which to place the Button. 182: // This panel will, in turn, be placed on the main border panel created 183: // above. 184: // 185: FlowPanel buttonPanel = FlowPanelFactory.create(context); 186: buttonPanel.setBackgroundColor(Color.WHITE); 187: buttonPanel.setHorizontalGap(6); 188: buttonPanel.setVerticalGap(6); 189: 190: 191: // Now add the button to the FlowPanel. There are no constraints applicable 192: // to widgets placed on a flow panel, so we don't use a special wrapper 193: // class like the BorderPanelWidget used above. 194: // 195: buttonPanel.addWidget(testButton); 196: 197: 198: // Now add the button panel to the south of the main border panel. 199: // 200: mainPanel.addWidget 201: ( BorderPanelWidgetFactory.create 202: (context, buttonPanel, BorderPanelWidget.SOUTH)); 203: 204: 205: // Next, we need to add the main panel (with its image and flow panel 206: // containing the button) to the frame. Frames have a tool bar, status 207: // bar and content area, each of which contain a single widget. Here we 208: // use setContent() to set the content of the frame to the main panel we 209: // created above. 210: // 211: frame.setContent(mainPanel); 212: 213: // And finaly, we make the frame visible. 214: // 215: frame.show(); 216: } 217: 218: 219: 220: // A main method is required if you want to be able to run an application 221: // stand-alone without using the armidale.api.LocalApplication class. 222: // The pattern of this main is fairly common in Java applications, 223: // in that it creates an instance of the enclosing class. In the case of 224: // armidale, it must also set the context in which to run the application. 225: // To run the application locally, we need to use the SwingContext which 226: // will cause the various widget factories to create objects that are 227: // implemented using swing. These object will therefore be displayed on the 228: // local computer. 229: // 230: public static void main(String[] args) { 231: 232: // create an instance of SimpleApp 233: // 234: SimpleApp app = new SimpleApp(); 235: 236: // set the apps context to an instance of SwingContext. 237: // 238: app.setContext(new SwingContext()); 239: 240: // the application is now ready to go. So start it. 241: // 242: app.start(); 243: } 244: 245:} 246:
<ArmidaleClass name="armidale.api.gui.Button"
extends="armidale.api.gui.Action"
abstract="yes"
>
<attribute name="text"
type="String"
default=""Button""
/>
<attribute name="icon"
type="@armidale.api.gui.Image"
default="null"
/>
<attribute name="textAlignment"
type="int"
constants="armidale.api.gui.constants.OrthogonalCompass"
default="EAST"
/>
</ArmidaleClass>