[skycastle-commits] SF.net SVN: skycastle: [463] trunk/skycastle/modules

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Fri, 18 Apr 2008 15:31:13 -0700

Revision: 463
          http://skycastle.svn.sourceforge.net/skycastle/?rev=463&view=rev
Author:   zzorn
Date:     2008-04-18 15:31:12 -0700 (Fri, 18 Apr 2008)

Log Message:
-----------
Separated the different functions of the previous client class into separate 
classes (ServerSessionHandler for communicating with server, ClientObject to 
provide client services and actions, and a SkycastleClient that initializes the 
client system).  
Also added a few UI classes (label, split panel), and created a rudimentary 
client UI with a working login and exit button.

Next step is to work on the way parameters are passed to invoked actions from 
UI components, so that we can use a text field to edit the server address, 
username, etc.

Modified Paths:
--------------
    trunk/skycastle/modules/client/pom.xml
    
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/SkycastleClient.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ClientContext.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObject.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObjectContext.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideContext.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/ProtocolCommunicator.java
    
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleClientSessionHandler.java
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/SwingClientUi.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java

Added Paths:
-----------
    
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ClientObject.java
    
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ExitAct.java
    
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/LoginAct.java
    
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ServerSessionHandler.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideGameObject.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/acting/AbstractAct.java
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/LabelUi.java
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/SplitPanelUi.java

Modified: trunk/skycastle/modules/client/pom.xml
===================================================================
--- trunk/skycastle/modules/client/pom.xml      2008-04-17 18:19:22 UTC (rev 
462)
+++ trunk/skycastle/modules/client/pom.xml      2008-04-18 22:31:12 UTC (rev 
463)
@@ -242,6 +242,11 @@
             <artifactId>skycastle-utils</artifactId>
             <version>0.0.4-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.skycastle</groupId>
+            <artifactId>skycastle-ui</artifactId>
+            <version>0.0.4-SNAPSHOT</version>
+        </dependency>
         <!--
                 <dependency>
                     <groupId>scala</groupId>

Added: 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ClientObject.java
===================================================================
--- 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ClientObject.java
                         (rev 0)
+++ 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ClientObject.java
 2008-04-18 22:31:12 UTC (rev 463)
@@ -0,0 +1,120 @@
+package org.skycastle.client;
+
+import org.skycastle.core.DefaultGameObject;
+import org.skycastle.core.GameContext;
+import org.skycastle.core.GameObject;
+import org.skycastle.core.acting.ActionImpl;
+import org.skycastle.ui.*;
+import org.skycastle.util.parameters.ParameterSetMetadataImpl;
+
+/**
+ * Client services wrapped in a client side {@link GameObject}.
+ *
+ * @author Hans Haggstrom
+ */
+public final class ClientObject
+        extends DefaultGameObject
+{
+
+    //======================================================================
+    // Private Fields
+
+    private ClientUi myClientUi = null;
+
+    //======================================================================
+    // Private Constants
+
+    private static final long serialVersionUID = 1L;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Other Public Methods
+
+    /**
+     * Starts the client - sets up some actions, and opens the UI.
+     */
+    public void start()
+    {
+        setupActions();
+
+        myClientUi = createUi();
+
+        myClientUi.start();
+    }
+
+    public void login( String host, long port, String username, String 
password )
+    {
+        // TODO: Handle multiple connected servers better.  Dissallow multiple 
logins with same username to the same server?
+
+        final ServerSessionHandler serverSessionHandler = new 
ServerSessionHandler( host,
+                                                                               
     port,
+                                                                               
     username,
+                                                                               
     password,
+                                                                               
     GameContext.getGameObjectContext() );
+
+        serverSessionHandler.login();
+    }
+
+    //======================================================================
+    // Private Methods
+
+
+    private void setupActions()
+    {
+        addAction( new ActionImpl( "exit",
+                                   new ParameterSetMetadataImpl(),
+                                   ExitAct.class,
+                                   "Exit",
+                                   "exits the application",
+                                   null,
+                                   null,
+                                   false ) );
+
+        addAction( new ActionImpl( "login",
+                                   new ParameterSetMetadataImpl(),
+                                   LoginAct.class,
+                                   "Login",
+                                   "logs in to the server",
+                                   null,
+                                   null,
+                                   false ) );
+    }
+
+    private ClientUi createUi()
+    {
+        final ClientUi clientUi = new SwingClientUi();
+
+        clientUi.setRootUi( createClientUi() );
+
+        return clientUi;
+    }
+
+
+    private static UiObject createClientUi()
+    {
+        // TODO: Later maybe read this from config file or a persistent 
storage?
+
+        final GameObject client = 
GameContext.getGameObjectContext().getGameObjectBoundToName( "client" );
+
+        final SplitPanelUi splitPanelUi = new SplitPanelUi();
+
+        final PanelUi clientBar = new PanelUi();
+        clientBar.addUi( new LabelUi( "This is the client bar" ) );
+        clientBar.addUi( new LabelUi( "<Connected server address goes here>" ) 
);
+        clientBar.addUi( new ButtonUi( client.getId(), "exit" ) );
+        //clientBar.addUi( new ButtonUi( ) ); // TODO: Create some named 
object that represents the client, that has methods like quit, logon to server, 
etc.
+
+        final PanelUi loginWindow = new PanelUi();
+        loginWindow.addUi( new LabelUi( "Server address:" ) );
+        loginWindow.addUi( new LabelUi( "<Input text field goes here>" ) );
+        loginWindow.addUi( new ButtonUi( client.getId(), "login" ) );
+
+        splitPanelUi.setFirstUi( clientBar );
+        splitPanelUi.setSecondUi( loginWindow );
+
+        return splitPanelUi;
+    }
+
+}

Added: 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ExitAct.java
===================================================================
--- 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ExitAct.java  
                            (rev 0)
+++ 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ExitAct.java  
    2008-04-18 22:31:12 UTC (rev 463)
@@ -0,0 +1,41 @@
+package org.skycastle.client;
+
+import org.skycastle.core.GameObject;
+import org.skycastle.core.acting.AbstractAct;
+import org.skycastle.core.acting.Act;
+import org.skycastle.messaging.MessageListener;
+import org.skycastle.util.parameters.ParameterSet;
+
+/**
+ * An {@link Act} that quits the client.
+ *
+ * @author Hans Haggstrom
+ */
+// TODO: Add are you sure dialog box
+public final class ExitAct
+        extends AbstractAct
+{
+
+    //======================================================================
+    // Private Constants
+
+    private static final long serialVersionUID = 1L;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Act Implementation
+
+    public long start( final GameObject hostObject,
+                       final MessageListener messageHandler, final 
ParameterSet actParameters, final ParameterSet configurationParameters )
+            throws Exception
+    {
+        // Pull the cables!
+        System.exit( 0 );
+
+        // TODO: A more gentle exit, that exits gracefully from servers, etc.
+        return -1;
+    }
+
+}

Added: 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/LoginAct.java
===================================================================
--- 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/LoginAct.java 
                            (rev 0)
+++ 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/LoginAct.java 
    2008-04-18 22:31:12 UTC (rev 463)
@@ -0,0 +1,56 @@
+package org.skycastle.client;
+
+import org.skycastle.core.GameObject;
+import org.skycastle.core.acting.AbstractAct;
+import org.skycastle.messaging.MessageListener;
+import org.skycastle.util.parameters.ParameterSet;
+
+/**
+ * Logs in to a server from the client
+ *
+ * @author Hans Haggstrom
+ */
+// TODO: How to pass client side object rfeferences to acts?
+// Maybe make acts just calls to methods defiened on custom game objects.
+public final class LoginAct
+        extends AbstractAct
+{
+
+    //======================================================================
+    // Private Constants
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * The default hostname.
+     */
+    private static final String DEFAULT_HOST = "localhost";
+
+    /**
+     * The default port.
+     */
+    private static final long DEFAULT_PORT = 1139L;
+
+    private static final String TEST_USER_NAME = "TestUser";
+    private static final String TEST_PASSWORD = "foo";
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Act Implementation
+
+    public long start( final GameObject hostObject,
+                       final MessageListener messageHandler,
+                       final ParameterSet actParameters,
+                       final ParameterSet configurationParameters )
+            throws Exception
+    {
+        // TODO: Fix better
+
+        ( (ClientObject) hostObject ).login( DEFAULT_HOST, DEFAULT_PORT, 
TEST_USER_NAME, TEST_PASSWORD );
+
+        return -1;
+    }
+
+}

Added: 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ServerSessionHandler.java
===================================================================
--- 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ServerSessionHandler.java
                         (rev 0)
+++ 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ServerSessionHandler.java
 2008-04-18 22:31:12 UTC (rev 463)
@@ -0,0 +1,291 @@
+package org.skycastle.client;
+
+import com.sun.sgs.client.ClientChannel;
+import com.sun.sgs.client.ClientChannelListener;
+import com.sun.sgs.client.simple.SimpleClient;
+import com.sun.sgs.client.simple.SimpleClientListener;
+import org.skycastle.core.GameObjectContext;
+import org.skycastle.messaging.Message;
+import org.skycastle.messaging.modifications.ModificationMessage;
+import org.skycastle.messaging.updates.UpdateMessage;
+import org.skycastle.protocol.ProtocolCommunicator;
+import org.skycastle.protocol.ProtocolException;
+import org.skycastle.protocol.negotiation.ClientSideProtocolNegotiator;
+import org.skycastle.protocol.negotiation.NegotiationStatus;
+import org.skycastle.protocol.registry.ProtocolRegistryImpl;
+import org.skycastle.util.ParameterChecker;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.net.PasswordAuthentication;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Listens to messages from a server we are connected to, and sends messages 
to it.
+ *
+ * @author Hans Haggstrom
+ */
+public final class ServerSessionHandler
+        extends ProtocolCommunicator
+        implements SimpleClientListener
+{
+
+    //======================================================================
+    // Private Fields
+
+    @SuppressWarnings( { "NonSerializableFieldInSerializableClass" } )
+    private final SimpleClient mySimpleClient;
+
+    private final String myHost;
+    private final String myPort;
+    private final String myUserName;
+    private final GameObjectContext myGameObjectContext;
+    private final char[] myPassword;
+
+    //======================================================================
+    // Private Constants
+
+    private static final int PROTOCOL_NEGOTIATION_TIMEOUT_MS = 10000;
+
+
+    /**
+     * The {@link Logger} for this class.
+     */
+    private static final Logger LOGGER = Logger.getLogger( 
SkycastleClient.class.getName() );
+
+    private static final String CLIENT_TYPE = "SkycastleClient";
+    private static final String CLIENT_VERSION = "0.1";
+    private static final ProtocolRegistryImpl PROTOCOL_REGISTRY = new 
ProtocolRegistryImpl();
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    /**
+     * Creates a new {@link ServerSessionHandler}.
+     *
+     * @param host     the hostname to connect to.  Either an IP number, or a 
domain name.
+     * @param port     the port to use when connecting
+     * @param userName username to use when logging in
+     * @param password password to use when logging in
+     * @param context  a context that incoming messages should be applied to.
+     */
+    public ServerSessionHandler( final String host, final long port, final 
String userName, final String password, final GameObjectContext context )
+    {
+        super( new ClientSideProtocolNegotiator( PROTOCOL_REGISTRY,
+                                                 CLIENT_TYPE,
+                                                 CLIENT_VERSION ),
+               PROTOCOL_NEGOTIATION_TIMEOUT_MS );
+
+        ParameterChecker.checkNotNull( host, "host" );
+        ParameterChecker.checkPositiveNonZeroInteger( port, "port" );
+        ParameterChecker.checkNotNull( userName, "userName" );
+        ParameterChecker.checkNotNull( password, "password" );
+        ParameterChecker.checkNotNull( context, "context" );
+
+        myHost = host;
+        myPort = String.valueOf( port );
+        myUserName = userName;
+        myPassword = password.toCharArray();
+        myGameObjectContext = context;
+
+        //noinspection ThisEscapedInObjectConstruction
+        mySimpleClient = new SimpleClient( this );
+    }
+
+    //----------------------------------------------------------------------
+    // ServerSessionListener Implementation
+
+    public ClientChannelListener joinedChannel( final ClientChannel 
clientChannel )
+    {
+        LOGGER.info( "Joined channel '" + clientChannel + "'." );
+
+        return null;
+    }
+
+
+    public void receivedMessage( final byte[] serverMessage )
+    {
+        try
+        {
+            handleReceivedEncodedMessage( serverMessage );
+        }
+        catch ( ProtocolException e )
+        {
+            LOGGER.warning( "Problem when decoding incoming message from 
server: " + e.getMessage() );
+        }
+    }
+
+
+    public void reconnecting()
+    {
+        LOGGER.info( "Reconnecting" );
+    }
+
+
+    public void reconnected()
+    {
+        LOGGER.info( "Reconnected" );
+    }
+
+
+    public void disconnected( final boolean b, final String s )
+    {
+        LOGGER.info( "Disconnected.  Graceful: '" + b + "'.  Message: '" + s + 
"'." );
+    }
+
+    //----------------------------------------------------------------------
+    // SimpleClientListener Implementation
+
+    public PasswordAuthentication getPasswordAuthentication()
+    {
+        return new PasswordAuthentication( myUserName, myPassword );
+    }
+
+
+    public void loggedIn()
+    {
+        LOGGER.info( "Logged In.  Now negotiationg protocol..." );
+
+        startProtocolNegotiations();
+    }
+
+
+    public void loginFailed( final String s )
+    {
+        LOGGER.info( "Login Failed.  Reason: '" + s + "'." );
+    }
+
+    //----------------------------------------------------------------------
+    // Other Public Methods
+
+    /**
+     * Initiates asynchronous login to the SGS server specified by the host 
and port properties.
+     */
+    @SuppressWarnings( { "AccessOfSystemProperties" } )
+    public void login()
+    {
+        try
+        {
+            final Properties connectProps = new Properties();
+            connectProps.setProperty( "host", myHost );
+            connectProps.setProperty( "port", myPort );
+            mySimpleClient.login( connectProps );
+        }
+        catch ( IOException e )
+        {
+            LOGGER.log( Level.SEVERE, "Problem when connecting to the 
server.", e );
+
+            disconnected( false, e.getMessage() );
+        }
+    }
+
+    /**
+     * Disconnects from the server gracefully.
+     */
+    public void disconnect()
+    {
+        mySimpleClient.logout( true );
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    @Override
+    protected void scheduleTimeoutCallback( final long timeout_ms )
+    {
+        final Thread timeoutTimer = new Thread( new Runnable()
+        {
+
+            public void run()
+            {
+                //noinspection UnusedCatchParameter
+                try
+                {
+                    Thread.sleep( timeout_ms );
+                }
+                catch ( InterruptedException e )
+                {
+                    // We were interrupted for some reason.  Stop waiting, and 
call the timeout.
+                }
+
+                // TODO: Assumes that the main game loop will run in the Swing 
event thread.  Check this.
+                //noinspection InnerClassTooDeeplyNested
+                SwingUtilities.invokeLater( new Runnable()
+                {
+
+                    public void run()
+                    {
+                        onTimeoutCallback();
+                    }
+
+                } );
+            }
+
+        } );
+
+        timeoutTimer.setDaemon( true ); // If the program exists, don't stay 
to wait for the timeout.
+
+        timeoutTimer.start();
+    }
+
+
+    @Override
+    protected void sendEncodedMessage( final byte[] encodedMessage )
+    {
+        try
+        {
+            mySimpleClient.send( encodedMessage );
+        }
+        catch ( IOException e )
+        {
+            LOGGER.log( Level.WARNING, "Problem when sending an encoded 
message to the server.", e );
+        }
+    }
+
+
+    @Override
+    protected void onProtocolNegotiationFailed( final NegotiationStatus status 
)
+    {
+        LOGGER.severe( "Could not negotiate a common protocol with the server: 
" + status.toString() );
+
+        disconnect();
+    }
+
+
+    @Override
+    protected void onProtocolNegotiationSucceeded( final String protocolId )
+    {
+        LOGGER.info( "Protocol negotiated." );
+    }
+
+
+    @Override
+    protected void onMessage( final Message message )
+            throws ProtocolException
+    {
+        LOGGER.log( Level.INFO, "Recieved a message: " + message );
+
+        //noinspection ChainOfInstanceofChecks
+        if ( message instanceof UpdateMessage )
+        {
+            final UpdateMessage updateMessage = (UpdateMessage) message;
+
+            updateMessage.applyStateChangeToModel( myGameObjectContext );
+        }
+        else if ( message instanceof ModificationMessage )
+        {
+            throw new ProtocolException(
+                    "The client does not accept any ModificationMessages, only 
UpdateMessages, but the incoming message was: " + message );
+        }
+        else
+        {
+            throw new ProtocolException( "Unknown message type: " + 
message.getClass() );
+        }
+    }
+
+}

Modified: 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/SkycastleClient.java
===================================================================
--- 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/SkycastleClient.java
      2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/SkycastleClient.java
      2008-04-18 22:31:12 UTC (rev 463)
@@ -1,24 +1,9 @@
 package org.skycastle.client;
 
-import com.sun.sgs.client.ClientChannel;
-import com.sun.sgs.client.ClientChannelListener;
-import com.sun.sgs.client.simple.SimpleClient;
-import com.sun.sgs.client.simple.SimpleClientListener;
 import org.skycastle.core.ClientContext;
 import org.skycastle.core.GameContext;
-import org.skycastle.messaging.Message;
-import org.skycastle.messaging.modifications.ModificationMessage;
-import org.skycastle.messaging.updates.UpdateMessage;
-import org.skycastle.protocol.ProtocolCommunicator;
-import org.skycastle.protocol.ProtocolException;
-import org.skycastle.protocol.negotiation.ClientSideProtocolNegotiator;
-import org.skycastle.protocol.negotiation.NegotiationStatus;
-import org.skycastle.protocol.registry.ProtocolRegistryImpl;
+import org.skycastle.core.GameObjectContext;
 
-import javax.swing.*;
-import java.io.IOException;
-import java.net.PasswordAuthentication;
-import java.util.Properties;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -54,50 +39,15 @@
 // as this implementation of ProtocolCommunicator is not intended to be 
serizliaed.
 @SuppressWarnings( { "serial" } )
 public class SkycastleClient
-        extends ProtocolCommunicator
-        implements SimpleClientListener
 {
 
     //======================================================================
-    // Private Fields
-
-    @SuppressWarnings( { "NonSerializableFieldInSerializableClass" } )
-    private final SimpleClient mySimpleClient;
-
-    //======================================================================
     // Private Constants
 
-    private static final int PROTOCOL_NEGOTIATION_TIMEOUT_MS = 10000;
-
     /**
-     * The name of the host property.
-     */
-    private static final String HOST_PROPERTY = "skycastle.host";
-
-    /**
-     * The default hostname.
-     */
-    private static final String DEFAULT_HOST = "localhost";
-
-    /**
-     * The name of the port property.
-     */
-    private static final String PORT_PROPERTY = "skycastle.port";
-
-    /**
-     * The default port.
-     */
-    private static final String DEFAULT_PORT = "1139";
-
-    private static final String TEST_USER_NAME = "TestUser";
-
-    /**
      * The {@link Logger} for this class.
      */
     private static final Logger LOGGER = Logger.getLogger( 
SkycastleClient.class.getName() );
-    private static final String CLIENT_TYPE = "SkycastleClient";
-    private static final String CLIENT_VERSION = "0.1";
-    private static final ProtocolRegistryImpl PROTOCOL_REGISTRY = new 
ProtocolRegistryImpl();
 
     //======================================================================
     // Public Methods
@@ -117,239 +67,42 @@
         // Initialize static context variable
         GameContext.setGameObjectContext( new ClientContext() );
 
-/*
-        // Do not show logging output below the WARNING level (JME outputs a 
lot of debugging info at INFO level).
-        // This way the console output is a bit more relevant.
-        LOGGER.setLevel( Level.WARNING );
-*/
+        // Create object that contains client side services
+        final ClientObject clientObject = createClientObject();
 
-        final SkycastleClient client = new SkycastleClient();
-
-        client.login();
-
-        // Idle forever
-        while ( true )
-        {
-            try
-            {
-                Thread.sleep( 1000 );
-            }
-            catch ( InterruptedException e )
-            {
-                e.printStackTrace();  //To change body of catch statement use 
File | Settings | File Templates.
-            }
-        }
+        // Start the client UI
+        clientObject.start();
     }
 
-    //----------------------------------------------------------------------
-    // Constructors
-
-    /**
-     * Creates a new {@link org.skycastle.client.SkycastleClient}.
-     */
-    public SkycastleClient()
-    {
-        super( new ClientSideProtocolNegotiator( PROTOCOL_REGISTRY,
-                                                 CLIENT_TYPE,
-                                                 CLIENT_VERSION ),
-               PROTOCOL_NEGOTIATION_TIMEOUT_MS );
-
-        mySimpleClient = new SimpleClient( this );
-    }
-
-    //----------------------------------------------------------------------
-    // ServerSessionListener Implementation
-
-    public ClientChannelListener joinedChannel( final ClientChannel 
clientChannel )
-    {
-        LOGGER.info( "Joined channel '" + clientChannel + "'." );
-
-        return null;
-    }
-
-
-    public void receivedMessage( final byte[] serverMessage )
-    {
-        try
-        {
-            handleReceivedEncodedMessage( serverMessage );
-        }
-        catch ( ProtocolException e )
-        {
-            LOGGER.warning( "Problem when decoding incoming message from 
server: " + e.getMessage() );
-        }
-    }
-
-
-    public void reconnecting()
-    {
-        LOGGER.info( "Reconnecting" );
-    }
-
-
-    public void reconnected()
-    {
-        LOGGER.info( "Reconnected" );
-    }
-
-
-    public void disconnected( final boolean b, final String s )
-    {
-        LOGGER.info( "Disconnected.  Graceful: '" + b + "'.  Message: '" + s + 
"'." );
-    }
-
-    //----------------------------------------------------------------------
-    // SimpleClientListener Implementation
-
-    public PasswordAuthentication getPasswordAuthentication()
-    {
-        // TODO: Query user about password
-
-        // DEBUG
-        return new PasswordAuthentication( TEST_USER_NAME, 
"testPassword".toCharArray() );
-    }
-
-
-    public void loggedIn()
-    {
-        LOGGER.info( "Logged In.  Now negotiationg protocol..." );
-
-        startProtocolNegotiations();
-    }
-
-
-    public void loginFailed( final String s )
-    {
-        LOGGER.info( "Login Failed.  Reason: '" + s + "'." );
-    }
-
     //======================================================================
-    // Protected Methods
+    // Private Methods
 
-    @Override
-    protected void scheduleTimeoutCallback( final long timeout_ms )
+    private static ClientObject createClientObject()
     {
-        final Thread timeoutTimer = new Thread( new Runnable()
-        {
-
-            public void run()
-            {
-                try
-                {
-                    Thread.sleep( timeout_ms );
-                }
-                catch ( InterruptedException e )
-                {
-                    // We were interrupted for some reason.  Stop waiting, and 
call the timeout.
-                }
-
-                // TODO: Assumes that the main game loop will run in the Swing 
event thread.  Check this.
-                SwingUtilities.invokeLater( new Runnable()
-                {
-
-                    public void run()
-                    {
-                        onTimeoutCallback();
-                    }
-
-                } );
-            }
-
-        } );
-
-        timeoutTimer.setDaemon( true ); // If the program exists, don't stay 
to wait for the timeout.
-
-        timeoutTimer.start();
-    }
-
-
-    @Override
-    protected void sendEncodedMessage( final byte[] encodedMessage )
-    {
         try
         {
-            mySimpleClient.send( encodedMessage );
-        }
-        catch ( IOException e )
-        {
-            LOGGER.log( Level.WARNING, "Problem when sending an encoded 
message to the server.", e );
-        }
-    }
+            final GameObjectContext context = 
GameContext.getGameObjectContext();
 
+            final ClientObject clientObject = context.createGameObject( 
ClientObject.class );
 
-    @Override
-    protected void onProtocolNegotiationFailed( final NegotiationStatus status 
)
-    {
-        LOGGER.severe( "Could not negotiate a common protocol with the server: 
" + status.toString() );
+            context.bindGameObjectToName( "client", clientObject );
 
-        disconnect();
-    }
-
-
-    @Override
-    protected void onProtocolNegotiationSucceeded( final String protocolId )
-    {
-        LOGGER.info( "Protocol negotiated." );
-    }
-
-
-    @Override
-    protected void onMessage( final Message message ) throws ProtocolException
-    {
-        LOGGER.log( Level.INFO, "Recieved a message: " + message );
-
-        if ( message instanceof UpdateMessage )
-        {
-            final UpdateMessage updateMessage = (UpdateMessage) message;
-
-            updateMessage.applyStateChangeToModel( 
GameContext.getGameObjectContext() );
+            return clientObject;
         }
-        else if ( message instanceof ModificationMessage )
+        catch ( InstantiationException e )
         {
-            throw new ProtocolException(
-                    "The client does not accept any ModificationMessages, only 
UpdateMessages, but the incoming message was: " + message );
+            LOGGER.log( Level.SEVERE, "Could not create client", e );
         }
-        else
+        catch ( IllegalAccessException e )
         {
-            throw new ProtocolException( "Unknown message type: " + 
message.getClass() );
+            LOGGER.log( Level.SEVERE, "Could not create client", e );
         }
-    }
 
-    //======================================================================
-    // Private Methods
-
-    /**
-     * Disconnects from the server gracefully.
-     */
-    private void disconnect()
-    {
-        mySimpleClient.logout( true );
+        throw new IllegalStateException( "Could not create ClientObject.  See 
log for details." );
     }
 
-
-    /**
-     * Initiates asynchronous login to the SGS server specified by the host 
and port properties.
-     */
-    // IDEA: This could be one action provided by a client side GameObject 
representing a server
-    @SuppressWarnings( { "AccessOfSystemProperties" } )
-    private void login()
+    private SkycastleClient()
     {
-        final String host = System.getProperty( HOST_PROPERTY, DEFAULT_HOST );
-        final String port = System.getProperty( PORT_PROPERTY, DEFAULT_PORT );
-
-        try
-        {
-            final Properties connectProps = new Properties();
-            connectProps.setProperty( "host", host );
-            connectProps.setProperty( "port", port );
-            mySimpleClient.login( connectProps );
-        }
-        catch ( Exception e )
-        {
-            LOGGER.log( Level.SEVERE, "Problem when connecting to the 
server.", e );
-
-            disconnected( false, e.getMessage() );
-        }
     }
 
 }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ClientContext.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ClientContext.java
    2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ClientContext.java
    2008-04-18 22:31:12 UTC (rev 463)
@@ -24,6 +24,8 @@
     private final Queue<CallbackEvent> myEvents = new 
PriorityQueue<CallbackEvent>();
     private final Set<IssueListener> myIssueListeners = new 
HashSet<IssueListener>( 5 );
 
+    private final Map<String, GameObject> myNamedGameObjects = new 
HashMap<String, GameObject>( 101 );
+
     private long myInGameClock_ms = 0L;
     private GameObjectId myRootObjectId;
 
@@ -100,10 +102,28 @@
     public GameObject createGameObject()
     {
         final DefaultGameObject gameObject = new DefaultGameObject();
-        gameObject.setId( createGameObjectId( gameObject ) );
+        setupGameObject( gameObject );
 
+        return gameObject;
+    }
+
+    private void setupGameObject( final GameObject gameObject )
+    {
+        // NOTE: Casting to default game object so we can set the id.  Might 
not work in all cases, maybe come up with better solution for the id setting?
+        ( (DefaultGameObject) gameObject ).setId( createGameObjectId( 
gameObject ) );
+
         addGameObject( gameObject );
+    }
 
+    public <T extends GameObject> T createGameObject( final Class<T> 
gameObjectType )
+            throws InstantiationException, IllegalAccessException
+    {
+        ParameterChecker.checkNotNull( gameObjectType, "gameObjectType" );
+
+        final T gameObject = gameObjectType.newInstance();
+
+        setupGameObject( gameObject );
+
         return gameObject;
     }
 
@@ -236,6 +256,16 @@
         myRootObjectId = rootObjectId;
     }
 
+    public void bindGameObjectToName( final String name, final GameObject 
gameObject )
+    {
+        myNamedGameObjects.put( name, gameObject );
+    }
+
+    public GameObject getGameObjectBoundToName( final String name )
+    {
+        return myNamedGameObjects.get( name );
+    }
+
     //======================================================================
     // Private Methods
 

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
        2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
        2008-04-18 22:31:12 UTC (rev 463)
@@ -20,6 +20,7 @@
 /**
  * Common functionality for all/most implementations of GameObject.
  */
+// TODO: Remove public constructors, so that GameObjects always have to be 
managed through the GameContext.
 // IDEA: Create some kind of GameObject specific debug stream listening system?
 // An admin readable mostRecentError field?
 

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObject.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObject.java   
    2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObject.java   
    2008-04-18 22:31:12 UTC (rev 463)
@@ -1,6 +1,5 @@
 package org.skycastle.core;
 
-import com.sun.sgs.app.ManagedObject;
 import com.sun.sgs.app.Task;
 import org.skycastle.core.acting.ActionFacade;
 import org.skycastle.core.property.PropertyFacade;
@@ -12,7 +11,7 @@
 // Return handlers pros: cleaner interfaces, leaner implementation, less 
places that change if a handler changes, less collision with POJOs.
 // Delegate pros: Simpler to use interface (but POJO usually provides a simple 
interface anyway? and other interfaces are used inside the framework..).
 public interface GameObject
-        extends ManagedObject, PropertyFacade, ActionFacade, MessagingFacade, 
Task
+        extends PropertyFacade, ActionFacade, MessagingFacade, Task
 {
 
     /**
@@ -20,4 +19,5 @@
      */
     GameObjectId getId();
 
+
 }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObjectContext.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObjectContext.java
        2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObjectContext.java
        2008-04-18 22:31:12 UTC (rev 463)
@@ -50,4 +50,25 @@
      * @return the created game object.  Can be read and written to.
      */
     GameObject createGameObject();
+
+    /**
+     * Creates a new game object of the specified type, registers it with the 
{@link GameObjectContext}, and returns it for
+     * reading and writing.
+     *
+     * @param gameObjectType a class that implements GameObject and has a 
no-arguments constructor.
+     *
+     * @return the created game object.  Can be read and written to.
+     */
+    <T extends GameObject> T createGameObject( Class<T> gameObjectType )
+            throws InstantiationException, IllegalAccessException;
+
+    /**
+     * Associates the specified name with the specified {@link GameObject}
+     */
+    void bindGameObjectToName( String name, GameObject gameObject );
+
+    /**
+     * @return the {@link GameObject} that is bound to the specified name, or 
null if none found.
+     */
+    GameObject getGameObjectBoundToName( String name );
 }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideContext.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideContext.java
        2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideContext.java
        2008-04-18 22:31:12 UTC (rev 463)
@@ -1,15 +1,14 @@
 package org.skycastle.core;
 
-import com.sun.sgs.app.AppContext;
-import com.sun.sgs.app.DataManager;
-import com.sun.sgs.app.ManagedReference;
+import com.sun.sgs.app.*;
+import org.skycastle.util.ParameterChecker;
 
 import java.io.Serializable;
 
 /**
  * @author Hans Häggström
  */
-public class ServerSideContext
+public final class ServerSideContext
         implements GameObjectContext, Serializable
 {
 
@@ -18,21 +17,27 @@
 
     private static final long serialVersionUID = 1L;
 
+    private static final String USER_BINDING_PREFIX = "Binding_";
+
     //======================================================================
     // Public Methods
 
     //----------------------------------------------------------------------
     // GameObjectContext Implementation
 
+    // TODO: Change to reflect that the GameContext internally manages all 
game objs.
 
     public GameObjectId createGameObjectId( final GameObject gameObject )
     {
+        ParameterChecker.checkNotNull( gameObject, "gameObject" );
+        checkImplementsManagedObject( gameObject );
+
         final DataManager dataManager = AppContext.getDataManager();
 
         // Assign unique ID, and bind it, so that we can access this object 
easily in the future
-        final ManagedReference reference = dataManager.createReference( 
gameObject );
+        final ManagedReference reference = dataManager.createReference( 
(ManagedObject) gameObject );
         final GameObjectId id = new GameObjectId( 
GameObjectId.GAME_OBJECT_BINDING_PREFIX + reference.getId().toString() );
-        dataManager.setBinding( id.toString(), gameObject );
+        dataManager.setBinding( id.toString(), (ManagedObject) gameObject );
         return id;
     }
 
@@ -52,7 +57,7 @@
 
         if ( retrievedGameObject != null && forModification )
         {
-            dataManager.markForUpdate( retrievedGameObject );
+            dataManager.markForUpdate( (ManagedObject) retrievedGameObject );
         }
 
         return retrievedGameObject;
@@ -66,7 +71,67 @@
 
     public GameObject createGameObject()
     {
-        throw new UnsupportedOperationException( "This method has not yet been 
implemented." ); // IMPLEMENT
+        final GameObject serverSideGameObject = new ServerSideGameObject();
+
+        // Assign ID and register the object.
+        createGameObjectId( serverSideGameObject );
+
+        return serverSideGameObject;
     }
 
+    public <T extends GameObject> T createGameObject( final Class<T> 
gameObjectType )
+            throws InstantiationException, IllegalAccessException
+    {
+        ParameterChecker.checkNotNull( gameObjectType, "gameObjectType" );
+        if ( !gameObjectType.isAssignableFrom( ServerSideGameObject.class ) )
+        {
+            throw new IllegalArgumentException( "The type of the object has to 
be a subtype of ServerSideGameObject on the server, but it was '" + 
gameObjectType + "' ." );
+        }
+
+        final T serverSideGameObject = gameObjectType.newInstance();
+
+        // Assign ID and register the object.
+        createGameObjectId( serverSideGameObject );
+
+        return serverSideGameObject;
+    }
+
+    public void bindGameObjectToName( final String name, final GameObject 
gameObject )
+    {
+        ParameterChecker.checkNotNull( gameObject, "gameObject" );
+        checkImplementsManagedObject( gameObject );
+
+
+        final DataManager dataManager = AppContext.getDataManager();
+
+        dataManager.setBinding( USER_BINDING_PREFIX + name, (ManagedObject) 
gameObject );
+    }
+
+    public GameObject getGameObjectBoundToName( final String name )
+    {
+        ParameterChecker.checkNotNull( name, "name" );
+
+        final DataManager dataManager = AppContext.getDataManager();
+
+        try
+        {
+            return dataManager.getBinding( USER_BINDING_PREFIX + name, 
GameObject.class );
+        }
+        catch ( NameNotBoundException e )
+        {
+            return null;
+        }
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private void checkImplementsManagedObject( final GameObject gameObject )
+    {
+        if ( !( gameObject instanceof ManagedObject ) )
+        {
+            throw new IllegalArgumentException( "On the server side, a 
GameObject must implement ManagedObject" );
+        }
+    }
+
 }

Added: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideGameObject.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideGameObject.java
                             (rev 0)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideGameObject.java
     2008-04-18 22:31:12 UTC (rev 463)
@@ -0,0 +1,30 @@
+package org.skycastle.core;
+
+import com.sun.sgs.app.ManagedObject;
+
+/**
+ * {@link GameObject} for use on server side.  Implements the {@link 
ManagedObject} interface.
+ *
+ * @author Hans Haggstrom
+ */
+public final class ServerSideGameObject
+        extends DefaultGameObject
+        implements ManagedObject
+{
+
+    //======================================================================
+    // Private Constants
+
+    private static final long serialVersionUID = 1L;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    ServerSideGameObject()
+    {
+    }
+
+}

Added: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/acting/AbstractAct.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/acting/AbstractAct.java
                               (rev 0)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/acting/AbstractAct.java
       2008-04-18 22:31:12 UTC (rev 463)
@@ -0,0 +1,49 @@
+package org.skycastle.core.acting;
+
+import org.skycastle.core.GameObject;
+import org.skycastle.messaging.MessageListener;
+import org.skycastle.util.parameters.ParameterSet;
+
+/**
+ * An abstract act implementation that provides empty implementations for 
doStep and stop.
+ *
+ * @author Hans Haggstrom
+ */
+public abstract class AbstractAct
+        implements Act
+{
+
+    //======================================================================
+    // Private Constants
+
+    private static final long serialVersionUID = 1L;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Act Implementation
+
+    public long doStep( final GameObject hostObject,
+                        final MessageListener messageHandler,
+                        final ParameterSet parameters,
+                        final ParameterSet configurationParameters,
+                        final long timeSinceLastCall_ms )
+            throws Exception
+    {
+        // Nothing to do
+
+        return -1; // Do not repeat
+    }
+
+    public void stop( final GameObject hostObject,
+                      final MessageListener messageHandler,
+                      final ParameterSet parameters,
+                      final ParameterSet configurationParameters,
+                      final long timeSinceLastCall_ms )
+            throws Exception
+    {
+        // Nothing to do
+    }
+
+}

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/ProtocolCommunicator.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/ProtocolCommunicator.java
 2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/ProtocolCommunicator.java
 2008-04-18 22:31:12 UTC (rev 463)
@@ -5,8 +5,6 @@
 import org.skycastle.protocol.negotiation.ProtocolNegotiator;
 import org.skycastle.util.ParameterChecker;
 
-import java.io.Serializable;
-
 /**
  * Takes care of negotiating a protocol, and after that forwarding decoded 
messages to a listener.
  * <p/>
@@ -18,7 +16,6 @@
  */
 // IDEA: Move logging / some error handling to this class, and avoid throwing 
out exceptions?
 public abstract class ProtocolCommunicator
-        implements Serializable
 {
 
     //======================================================================
@@ -207,7 +204,8 @@
      *
      * @param message the deocoded message.
      */
-    protected abstract void onMessage( final Message message ) throws 
ProtocolException;
+    protected abstract void onMessage( final Message message )
+            throws ProtocolException;
 
     //======================================================================
     // Private Methods
@@ -241,7 +239,8 @@
     }
 
 
-    private void handleMessage( final byte[] byteMessage ) throws 
ProtocolException
+    private void handleMessage( final byte[] byteMessage )
+            throws ProtocolException
     {
         // Decode incoming message and notify decendant implementation
         onMessage( myProtocolNegotiator.getProtocol().decode( byteMessage ) );

Modified: 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleClientSessionHandler.java
===================================================================
--- 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleClientSessionHandler.java
        2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleClientSessionHandler.java
        2008-04-18 22:31:12 UTC (rev 463)
@@ -1,6 +1,8 @@
 package org.skycastle.server;
 
-import com.sun.sgs.app.*;
+import com.sun.sgs.app.ClientSession;
+import com.sun.sgs.app.ClientSessionListener;
+import com.sun.sgs.app.Task;
 import org.skycastle.core.*;
 import org.skycastle.messaging.Message;
 import org.skycastle.messaging.modifications.ModificationMessage;
@@ -126,7 +128,8 @@
     // Task Implementation
 
 
-    public void run() throws Exception
+    public void run()
+            throws Exception
     {
         onTimeoutCallback();
     }
@@ -186,7 +189,8 @@
 
 
     @Override
-    protected void onMessage( final Message message ) throws ProtocolException
+    protected void onMessage( final Message message )
+            throws ProtocolException
     {
         // Check the message sender id so that the client is not claiming to 
be someone else.
         if ( !myClientAccountId.equals( message.getSenderId() ) )
@@ -240,21 +244,16 @@
      */
     private GameObject getUserAccount( final String userLoginName )
     {
-        final DataManager dataManager = AppContext.getDataManager();
-
         final String bindingName = ACCOUNT_PREFIX + userLoginName;
 
-        GameObject clientAccount;
-
-        try
+        final GameObjectContext context = GameContext.getGameObjectContext();
+        GameObject clientAccount = context.getGameObjectBoundToName( 
bindingName );
+        if ( clientAccount == null )
         {
-            clientAccount = dataManager.getBinding( bindingName, 
GameObject.class );
-        }
-        catch ( NameNotBoundException e )
-        {
             // If client doesn't yet have any account, create a new one
 
-            clientAccount = new DefaultGameObject();
+            clientAccount = context.createGameObject();
+
             // TODO: Do we need to store the client user name with the 
account?  Any other data?
             // TODO: This is a game / server extension point, as different 
servers could have different options and provided UI layouts here.
             // By default, we could however have some standard stuff like 
information about the server
@@ -262,7 +261,7 @@
             // TODO: Use some server configuration property or object to 
determine which class should be instantiated as the account object for new 
users.
 
             // Store created account for future access
-            dataManager.setBinding( bindingName, clientAccount );
+            context.bindGameObjectToName( bindingName, clientAccount );
 
             myClientAccountId = clientAccount.getId();
         }

Added: trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/LabelUi.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/LabelUi.java      
                        (rev 0)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/LabelUi.java      
2008-04-18 22:31:12 UTC (rev 463)
@@ -0,0 +1,68 @@
+package org.skycastle.ui;
+
+import javax.swing.*;
+
+/**
+ * A text label.
+ *
+ * @author Hans Haggstrom
+ */
+public final class LabelUi
+        extends UiObject
+{
+
+    //======================================================================
+    // Private Fields
+
+    private String myText = "";
+    private JLabel myLabel = null;
+
+    //======================================================================
+    // Private Constants
+
+    private static final long serialVersionUID = 1L;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    public LabelUi()
+    {
+    }
+
+    public LabelUi( final String text )
+    {
+        myText = text;
+    }
+
+    //----------------------------------------------------------------------
+    // Other Public Methods
+
+    public String getText()
+    {
+        return myText;
+    }
+
+    public void setText( final String text )
+    {
+        myText = text;
+
+        if ( myLabel != null )
+        {
+            myLabel.setText( myText );
+        }
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    @Override
+    protected JComponent createUi()
+    {
+        myLabel = new JLabel( myText );
+        return myLabel;
+    }
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/SplitPanelUi.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/SplitPanelUi.java 
                        (rev 0)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/SplitPanelUi.java 
2008-04-18 22:31:12 UTC (rev 463)
@@ -0,0 +1,102 @@
+package org.skycastle.ui;
+
+import javax.swing.*;
+import java.awt.BorderLayout;
+
+/**
+ * A panel that is split into two areas with a horizontal or vertical divider.
+ *
+ * @author Hans Haggstrom
+ */
+public class SplitPanelUi
+        extends UiObject
+{
+
+    //======================================================================
+    // Private Fields
+
+    private JSplitPane mySplitPane = null;
+
+    private int mySize;
+    private boolean myVerticalOrientation; // If false, orientation is 
horizontal.  Should really be an enum instead.
+    private boolean myFirstEdgeAsSizeAnchor;// Size is relative to first or 
second edge - should really be an enum.
+    private boolean mySizeIsInPercent; // Relative or absolute size - should 
really be an enum.  if false, size is in pixels, if true, in %
+
+    private UiObject myFirstUi;
+    private UiObject mySecondUi;
+    private JPanel myFirstPanel;
+    private JPanel mySecondPanel;
+
+    //======================================================================
+    // Private Constants
+
+    private static final long serialVersionUID = 1L;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Other Public Methods
+
+    public UiObject getFirstUi()
+    {
+        return myFirstUi;
+    }
+
+    public void setFirstUi( final UiObject firstUi )
+    {
+        changeUi( myFirstUi, firstUi, myFirstPanel );
+        myFirstUi = firstUi;
+    }
+
+    public UiObject getSecondUi()
+    {
+        return mySecondUi;
+    }
+
+    public void setSecondUi( final UiObject secondUi )
+    {
+        changeUi( mySecondUi, secondUi, mySecondPanel );
+        mySecondUi = secondUi;
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    @Override
+    protected JComponent createUi()
+    {
+        myFirstPanel = new JPanel( new BorderLayout() );
+        mySecondPanel = new JPanel( new BorderLayout() );
+        mySplitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT, myFirstPanel, 
mySecondPanel );
+
+        changeUi( null, myFirstUi, myFirstPanel );
+        changeUi( null, mySecondUi, mySecondPanel );
+
+//        mySplitPane.setEnabled( false );
+
+        mySplitPane.setDividerLocation( 100 );
+        // TODO: Listen to size changes, and update divider location
+
+        return mySplitPane;
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private void changeUi( final UiObject oldValue, final UiObject newValue, 
final JPanel hostPanel )
+    {
+        if ( oldValue != null &&
+             hostPanel != null )
+        {
+            hostPanel.remove( oldValue.getUi() );
+        }
+
+        if ( newValue != null &&
+             hostPanel != null )
+        {
+            hostPanel.add( newValue.getUi(), BorderLayout.CENTER );
+        }
+    }
+
+}

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/SwingClientUi.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/SwingClientUi.java    
    2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/SwingClientUi.java    
    2008-04-18 22:31:12 UTC (rev 463)
@@ -1,6 +1,7 @@
 package org.skycastle.ui;
 
 import javax.swing.*;
+import java.awt.BorderLayout;
 import java.awt.Dimension;
 
 /**
@@ -35,7 +36,7 @@
 
         myMainFrame.setVisible( true );
 
-        myRootPanel = new JPanel();
+        myRootPanel = new JPanel( new BorderLayout() );
         myRootPanel.setPreferredSize( DEFAULT_SIZE );
         myMainFrame.getContentPane().add( myRootPanel );
 
@@ -75,7 +76,7 @@
         if ( myMainFrame != null &&
              myRootUi != null )
         {
-            myRootPanel.add( myRootUi.getUi() );
+            myRootPanel.add( myRootUi.getUi(), BorderLayout.CENTER );
         }
 
         if ( myRootPanel != null )

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
        2008-04-17 18:19:22 UTC (rev 462)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
        2008-04-18 22:31:12 UTC (rev 463)
@@ -117,7 +117,7 @@
      *
      * @throws IllegalArgumentException if the check fails.
      */
-    public static void checkPositiveNonZeroInteger( int parameter, String 
parameterName )
+    public static void checkPositiveNonZeroInteger( long parameter, String 
parameterName )
     {
         if ( parameter <= 0 )
         {


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

Other related posts:

  • » [skycastle-commits] SF.net SVN: skycastle: [463] trunk/skycastle/modules