Beginnings of runtime control panel stuff.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1428 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2002-06-07 06:22:24 +00:00
parent b81ab2f176
commit 6202c1a463
8 changed files with 506 additions and 0 deletions
@@ -0,0 +1,34 @@
//
// $Id: AdminService.java,v 1.1 2002/06/07 06:22:24 mdb Exp $
package com.threerings.admin.client;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationDirector;
import com.threerings.admin.Log;
import com.threerings.admin.data.AdminCodes;
/**
* Handles the client side of the admin invocation services.
*/
public class AdminService
implements AdminCodes
{
/**
* Requests the list of config objects. This will result in a call to
*
* <pre>
* public void handleConfigInfoResponse (int invid, String[] keys,
* int[] oids)
* </pre>
*
* on the response target.
*/
public static void getConfigInfo (Client client, Object rsptarget)
{
InvocationDirector invdir = client.getInvocationDirector();
invdir.invoke(MODULE_NAME, GET_CONFIG_INFO_REQUEST, null, rsptarget);
Log.debug("Sent getConfigInfo request.");
}
}
@@ -0,0 +1,79 @@
//
// $Id: ConfigEditorPanel.java,v 1.1 2002/06/07 06:22:24 mdb Exp $
package com.threerings.admin.client;
import javax.swing.JTabbedPane;
import javax.swing.event.AncestorEvent;
import com.samskivert.swing.event.AncestorAdapter;
import com.samskivert.util.StringUtil;
import com.threerings.media.SafeScrollPane;
import com.threerings.presents.util.PresentsContext;
import com.threerings.admin.Log;
/**
* Fetches a list of the configuration objects in use by the server and
* displays their fields in a tree widget to be viewed and edited.
*/
public class ConfigEditorPanel extends JTabbedPane
{
/**
* Constructs an editor panel which will use the supplied context to
* access the distributed object services.
*/
public ConfigEditorPanel (PresentsContext ctx)
{
_ctx = ctx;
// when we're hidden, we want to clear out our subscriptions
addAncestorListener(new AncestorAdapter () {
public void ancestorRemoved (AncestorEvent event) {
cleanup();
}
});
// if we have no children, ship off a getConfigInfo request to
// find out what config objects are available for editing
if (getComponentCount() == 0) {
Log.info("Sending get config info.");
AdminService.getConfigInfo(_ctx.getClient(), this);
}
}
/**
* Called in response to our getConfigInfo server-side service
* request.
*/
public void handleConfigInfo (int invid, String[] keys, int[] oids)
{
Log.info("Got config info: " + StringUtil.toString(keys));
// create object editor panels for each of the categories
for (int ii = 0; ii < keys.length; ii++) {
ObjectEditorPanel panel =
new ObjectEditorPanel(_ctx, keys[ii], oids[ii]);
SafeScrollPane scrolly = new SafeScrollPane(panel);
addTab(keys[ii], scrolly);
}
}
/**
* Called when the panel is hidden; this instructs all of our object
* editors to clear out their subscriptions.
*/
protected void cleanup ()
{
int ccount = getComponentCount();
for (int ii = 0; ii < ccount; ii++) {
SafeScrollPane scrolly = (SafeScrollPane)getComponent(ii);
ObjectEditorPanel opanel = (ObjectEditorPanel)
scrolly.getViewport().getView();
opanel.cleanup();
}
}
/** Our client context. */
protected PresentsContext _ctx;
}
@@ -0,0 +1,97 @@
//
// $Id: FieldEditor.java,v 1.1 2002/06/07 06:22:24 mdb Exp $
package com.threerings.admin.client;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import com.samskivert.swing.HGroupLayout;
import com.threerings.presents.dobj.AttributeChangeListener;
import com.threerings.presents.dobj.AttributeChangedEvent;
import com.threerings.presents.dobj.DObject;
import com.threerings.presents.util.PresentsContext;
/**
* Used to display and edit a particular distributed object field.
*/
public class FieldEditor extends JPanel
implements AttributeChangeListener, ActionListener
{
public FieldEditor (PresentsContext ctx, Field field, DObject object)
{
_ctx = ctx;
_field = field;
_object = object;
// create our interface elements
setLayout(new HGroupLayout(HGroupLayout.STRETCH));
// set up our default border
updateBorder(false);
// a label to display the field name
add(_label = new JLabel(_field.getName()), HGroupLayout.FIXED);
// and a text entry field to display the field value
String value = "";
try {
value = String.valueOf(_field.get(_object));
} catch (IllegalAccessException iae) {
value = "<error>";
}
add(_value = new JTextField(value));
_value.addActionListener(this);
}
// documentation inherited from interface
public void attributeChanged (AttributeChangedEvent event)
{
_value.setText(String.valueOf(event.getValue()));
updateBorder(false);
}
// documentation inherited from interface
public void actionPerformed (ActionEvent event)
{
if (_field.getType().equals(Integer.class) ||
_field.getType().equals(Integer.TYPE)) {
try {
Integer value = new Integer(_value.getText());
AttributeChangedEvent ace = new AttributeChangedEvent(
_object.getOid(), _field.getName(), value);
_ctx.getDObjectManager().postEvent(ace);
} catch (NumberFormatException nfe) {
updateBorder(true);
}
}
}
/**
* Sets the appropriate border on this field editor based on whether
* or not the field is modified.
*/
protected void updateBorder (boolean modified)
{
if (modified) {
setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.red));
} else {
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
}
protected PresentsContext _ctx;
protected Field _field;
protected DObject _object;
protected JLabel _label;
protected JTextField _value;
}
@@ -0,0 +1,119 @@
//
// $Id: ObjectEditorPanel.java,v 1.1 2002/06/07 06:22:24 mdb Exp $
package com.threerings.admin.client;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import javax.swing.BorderFactory;
import javax.swing.event.AncestorEvent;
import com.samskivert.swing.VGroupLayout;
import com.samskivert.swing.ScrollablePanel;
import com.samskivert.swing.event.AncestorAdapter;
import com.threerings.presents.dobj.DObject;
import com.threerings.presents.dobj.ObjectAccessException;
import com.threerings.presents.dobj.Subscriber;
import com.threerings.presents.util.PresentsContext;
import com.threerings.admin.Log;
/**
* Used to edit the distributed object fields of a particular
* configuration object. When the panel is first shown, it will subscribe
* to the object and display its fields. It will not automatically
* unsubscribe when it is hidden, but rather {@link #cleanup} must be
* called to let it know that it's not going to be shown again soon and it
* is safe for it to clear out its subscription.
*
* @see ConfigEditorPanel
*/
public class ObjectEditorPanel extends ScrollablePanel
implements Subscriber
{
/**
* Creates an object editor panel for the specified configuration
* object.
*/
public ObjectEditorPanel (PresentsContext ctx, String key, int oid)
{
super(new VGroupLayout(VGroupLayout.NONE, VGroupLayout.STRETCH,
5, VGroupLayout.TOP));
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
// keep this business around
_ctx = ctx;
_key = key;
_oid = oid;
// when we're hidden, we want to clear out our subscriptions
addAncestorListener(new AncestorAdapter () {
public void ancestorAdded (AncestorEvent event) {
// subscribe to our object the first time we're shown
if (_object == null) {
_ctx.getDObjectManager().subscribeToObject(
_oid, ObjectEditorPanel.this);
}
}
});
}
// documentation inherited from interface
public boolean getScrollableTracksViewportWidth ()
{
return true;
}
/**
* This method must be called to let the object editor panel know that
* it's OK for it to remove its subscription to its config object.
*/
public void cleanup ()
{
if (_object != null) {
_ctx.getDObjectManager().unsubscribeFromObject(_oid, this);
_object = null;
}
// clear out our field editors
removeAll();
}
// documentation inherited from interface
public void objectAvailable (DObject object)
{
// keep this for later
_object = object;
// create our field editors
try {
Field[] fields = object.getClass().getFields();
for (int ii = 0; ii < fields.length; ii++) {
// if the field is anything but a plain old public field,
// we don't want to edit it
if (fields[ii].getModifiers() == Modifier.PUBLIC) {
add(new FieldEditor(_ctx, fields[ii], _object));
}
}
} catch (SecurityException se) {
Log.warning("Unable to introspect DObject!? " + se);
}
revalidate();
repaint();
}
// documentation inherited from interface
public void requestFailed (int oid, ObjectAccessException cause)
{
Log.warning("Unable to subscribe to config object: " + cause);
}
protected PresentsContext _ctx;
protected String _key;
protected int _oid;
protected DObject _object;
}