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. 50:// 51:// Because this is an armidale application, it can be run stand-alone or over 52:// a network using the armidale launcher. 53:// 54: 55: 56:// All armidale applications must extend armidale.api.Application or an extension of it. 57:// 58:public class SimpleApp extends Application { 59: 60: 61: public void init() { 62: 63: // This is where the main work is done. The init() method is declared in armidale.api.Application 64: // and is called as part of the application execution (see the armidale.api.Application.run() 65: // method). 66: // 67: 68: // We start by creating a frame using the armidale.api.gui.FrameFactory. This factory creates 69: // implementations of the armidale.api.gui.Frame interface based on the specified context (usually 70: // server or local swing). The context parameter used below is declared in armidale.api.Application 71: // (our parent class) and is set by the environment starting the application. In the standalone 72: // case this is set in a main method like the one defined later in this class. In the case of a 73: // server environment, it is set by the armidale server in response to a connection 74: // request from a client. 75: // 76: // The main point here is that the application developer doesn't have to worry about what 77: // context is set to. He just passes it as a parameter the the various factories and other 78: // API methods. 79: // 80: Frame frame = FrameFactory.create(context); 81: 82: 83: // Armidale handles events using a callback mechanism. When an event is generated by a widget 84: // (eg. a user clicks a button) a specific method of each associated callback object is called. 85: // For example, when a Frame is closed, a frame close event is generated. This 86: // event results in a call to the windowClosing() method of each associate WindowCallback object. 87: // 88: // In the following statement we add a callback to the frame to handle window close events 89: // (ie. when the user clicks the close icon at the top of the window). As a convenience, armidale 90: // includes a simple class (armidale.api.gui.WindowCloseCallback) that implements various 91: // options regarding the closing of frames. Here we have chosen to stop the application when 92: // the user closes the frame. 93: // 94: frame.addWindowCallback(new WindowCloseCallback(context, WindowCloseCallback.STOP_APPLICATION_ON_CLOSE)); 95: 96: 97: // Complete the initialization of the frame by setting its title, size etc. 98: // 99: frame.setTitle("Simple Application"); 100: frame.setSize(new Size(420, 200)); 101: frame.setAlignment(Frame.CENTER); 102: frame.setResizable(false); 103: 104: 105: // The image and button will be displayed on a BorderPanel. Create the main panel 106: // and set its background color. Note that the Color class here is an armidale.api.gui.Color, 107: // not a java.awt.Color 108: // 109: BorderPanel mainPanel = BorderPanelFactory.create(context); 110: mainPanel.setBackgroundColor(Color.WHITE); 111: 112: 113: // Create the image and set the image data to the contents of a specified file. 114: // 115: // By using the setFile() method to set the image data, this application, when run on a server, 116: // will ask the client to try and load the image from the client filesystem. If the image 117: // is not available on the client, it will downloaded from the server. 118: // 119: Image image = ImageFactory.create(context); 120: image.setFile(new File("images/armidaledemo.png")); 121: 122: 123: // Create a label, based on the above image and set its alignment 124: // 125: Label label = LabelFactory.create(context); 126: label.setImage(image); 127: label.setAlignment(Label.CENTER); 128: 129: 130: // Add the label created above to the main panel. To add a widget to a border panel, it needs to 131: // be wrapped up in a BorderPanelWidget along with its position (constraints) on the border panel 132: // (ie. north, south, east, west or center). Note that this pattern is used for many of the armidale 133: // panels (eg. GridPanel and GridPanelWidget). 134: // 135: mainPanel.addWidget(BorderPanelWidgetFactory.create(context, label, BorderPanelWidget.CENTER)); 136: 137: 138: // Following the same pattern of widget creation, we now create a button and set some its 139: // properties 140: // 141: PushButton testButton = PushButtonFactory.create(context); 142: testButton.setText("Test Events"); 143: testButton.setPreferredSize(new Size(150, 25)); 144: 145: 146: // For convenience, armidale provides a Debug implementation of all callback classes. 147: // These Debug classes print details of events generated by associated widgets. 148: // 149: // In the following code we add to the button a pre-built ActionCallbackDebug object which displays 150: // a debug message when the button is pressed. 151: // 152: testButton.addActionCallback(new ActionCallbackDebug(context)); 153: 154: 155: // We are now going to create a FlowPanel on which to place the Button. This panel will, in turn, 156: // be placed on the main border panel created above. 157: // 158: FlowPanel buttonPanel = FlowPanelFactory.create(context); 159: buttonPanel.setBackgroundColor(Color.WHITE); 160: buttonPanel.setHorizontalGap(6); 161: buttonPanel.setVerticalGap(6); 162: 163: 164: // Now add the button to the FlowPanel. There are no constraints applicable to widgets placed on a 165: // flow panel, so we don't use a special wrapper class like the BorderPanelWidget used above. 166: // 167: buttonPanel.addWidget(testButton); 168: 169: 170: // Now add the button panel to the south of the main border panel. 171: // 172: mainPanel.addWidget(BorderPanelWidgetFactory.create(context, buttonPanel, BorderPanelWidget.SOUTH)); 173: 174: 175: // Next, we need to add the main panel (with its image and flow panel containing the button) to the 176: // frame. Frames have a tool bar, status bar and content area, each of which contain a single 177: // widget. Here we use setContent() to set the content of the frame to the main panel we 178: // created above. 179: // 180: frame.setContent(mainPanel); 181: 182: // And finaly, we make the frame visible. 183: // 184: frame.show(); 185: } 186: 187: 188: 189: // A main method is required if you want to be able to run an application 190: // stand-alone. The pattern of this main is fairly common in Java applications, 191: // in that it creates an instance of the enclosing class. In the case of armidale, 192: // it must also set the context in which to run the application. To run the application 193: // locally, we need to use the SwingContext which will cause the various widget factories 194: // to create objects that are implemented using swing. These object will therefore be 195: // displayed on the local computer. 196: // 197: public static void main(String[] args) { 198: 199: // create an instance of SimpleApp 200: // 201: SimpleApp app = new SimpleApp(); 202: 203: // set the apps context to an instance of SwingContext. 204: // 205: app.setContext(new SwingContext()); 206: 207: // the application is now ready to go. So start it. 208: // 209: app.start(); 210: } 211: 212:} 213: