Sweet Mary, mother of Jesus! Another fucking refactor. It turns out that

the way I was doing inheritance between the display and editable scene
implementations was not copacetic. The new method (which is for every
editable scene impl to delegate to a display scene impl so that regardless
of how far along you are on the inheritance chain, there are only ever two
actual objects, the display impl and the editable impl) is somewhat
cleaner, but makes it clear that no method can work as nicely as it would
were we to have mutliple inheritance.

The basic problem is that the editable versions of the scenes have to be
able to manipulate the instance variables in the display versions of the
scenes because they have to keep them up to date so that they are
displaying the right thing. As the editable versions are in different
packages, they don't have access to the display instance variables, so the
display versions simply have to make available enough "editable"
functionality to allow the editable versions to get their job done. It's
more coupling that I'd like, but at least it's only between the display
and editable versions across the inheritance hierarchy rather than down
the hierarchy.

Blah.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@745 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-12-05 08:45:06 +00:00
parent 7c60cb5df2
commit 2c27824718
5 changed files with 170 additions and 198 deletions
@@ -1,8 +1,10 @@
//
// $Id: DisplaySpotScene.java,v 1.2 2001/11/29 00:16:11 mdb Exp $
// $Id: DisplaySpotScene.java,v 1.3 2001/12/05 08:45:05 mdb Exp $
package com.threerings.whirled.spot.client;
import java.util.List;
import com.threerings.whirled.client.DisplayScene;
import com.threerings.whirled.spot.data.Location;
@@ -21,13 +23,13 @@ public interface DisplaySpotScene extends DisplayScene
public int getDefaultEntranceId ();
/**
* Returns an array of the locations in this scene (including portals
* Returns a list of the locations in this scene (including portals
* which will be instances of {@link Portal}).
*/
public Location[] getLocations ();
public List getLocations ();
/**
* Returns an array of the portals in this scene.
* Returns a list of the portals in this scene.
*/
public Portal[] getPortals ();
public List getPortals ();
}
@@ -1,8 +1,11 @@
//
// $Id: DisplaySpotSceneImpl.java,v 1.3 2001/12/05 03:38:09 mdb Exp $
// $Id: DisplaySpotSceneImpl.java,v 1.4 2001/12/05 08:45:05 mdb Exp $
package com.threerings.whirled.spot.client;
import java.util.ArrayList;
import java.util.List;
import com.threerings.crowd.data.PlaceConfig;
import com.threerings.whirled.client.DisplaySceneImpl;
@@ -30,8 +33,8 @@ public class DisplaySpotSceneImpl extends DisplaySceneImpl
// sort out our locations and portals
int lcount = model.locationIds.length;
int pcount = model.portalIds.length;
_portals = new Portal[pcount];
_locations = new Location[lcount - pcount];
_portals = new ArrayList(pcount);
_locations = new ArrayList(lcount - pcount);
// because the portals ids are in the same order as the location
// ids, we can parse them in one pass
@@ -43,29 +46,22 @@ public class DisplaySpotSceneImpl extends DisplaySceneImpl
if (model.locationIds[i] == pid) {
// add this portal to the portals array
_portals[pidx] = createPortal();
populatePortal(model, _portals[pidx], i, pidx);
loc = _portals[pidx];
Portal port = new Portal();
populatePortal(model, port, i, pidx);
_portals.add(port);;
loc = port;
pidx++;
} else {
loc = createLocation();
loc = new Location();
populateLocation(model, loc, i);
}
// everything goes into the locations array
_locations[i] = loc;
_locations.add(loc);
}
}
/**
* Returns a new location instance.
*/
protected Location createLocation ()
{
return new Location();
}
/**
* Populates a location instance with the specified index, using
* information from the model.
@@ -84,14 +80,6 @@ public class DisplaySpotSceneImpl extends DisplaySceneImpl
loc.clusterIndex = model.locationClusters[lidx];
}
/**
* Returns a new portal instance.
*/
protected Portal createPortal ()
{
return new Portal();
}
/**
* Populates a portal instance with the specified index, using
* information from the model.
@@ -119,13 +107,13 @@ public class DisplaySpotSceneImpl extends DisplaySceneImpl
}
// documentation inherited
public Location[] getLocations ()
public List getLocations ()
{
return _locations;
}
// documentation inherited
public Portal[] getPortals ()
public List getPortals ()
{
return _portals;
}
@@ -133,9 +121,9 @@ public class DisplaySpotSceneImpl extends DisplaySceneImpl
/** The data that makes up our scene. */
protected SpotSceneModel _model;
/** An array of the locations (and portals) in this scene. */
protected Location[] _locations;
/** A list of the locations (and portals) in this scene. */
protected ArrayList _locations;
/** An array of just the portals in this scene. */
protected Portal[] _portals;
/** A list of just the portals in this scene. */
protected ArrayList _portals;
}
@@ -1,10 +1,10 @@
//
// $Id: EditableSpotSceneImpl.java,v 1.6 2001/12/05 07:38:54 mdb Exp $
// $Id: EditableSpotSceneImpl.java,v 1.7 2001/12/05 08:45:06 mdb Exp $
package com.threerings.whirled.tools.spot;
import java.util.ArrayList;
import com.samskivert.util.ListUtil;
import java.util.List;
import com.threerings.crowd.data.PlaceConfig;
import com.threerings.whirled.tools.EditableSceneModel;
@@ -34,43 +34,9 @@ import com.threerings.whirled.spot.Log;
*
* @see com.threerings.whirled.tools.EditableScene
*/
public class EditableSpotSceneImpl
extends DisplaySpotSceneImpl
public class EditableSpotSceneImpl extends EditableSceneImpl
implements EditableSpotScene
{
/**
* Creates an instance that will obtain data from the supplied scene
* model and update it when changes are made.
*/
public EditableSpotSceneImpl (EditableSpotSceneModel model)
{
super(model.spotSceneModel, null);
// keep track of this
_emodel = model;
// Java doesn't support multiple inheritance (we'll let the reader
// decide whether or not that's unfortunate), so we have to
// instantiate an EditableSceneImpl delegate to handle the
// extensions to DisplayScene provided by EditableScene because
// we're extending from the DisplaySceneImpl class chain
_edelegate = new EditableSceneImpl(model);
// go through and finish populating our editable portals
for (int i = 0; i < _portals.length; i++) {
EditablePortal port = (EditablePortal)_portals[i];
port.name = _emodel.portalNames[i];
port.targetSceneName = (String)_emodel.neighborNames.get(i);
port.targetPortalName = _emodel.targetPortalNames[i];
}
}
// documentation inherited
protected Portal createPortal ()
{
return new EditablePortal();
}
/**
* Creates an instance that will create and use a blank scene model.
*/
@@ -79,64 +45,76 @@ public class EditableSpotSceneImpl
this(EditableSpotSceneModel.blankSpotSceneModel());
}
// documentation inherited
public void setId (int sceneId)
/**
* Creates an instance that will obtain data from the supplied scene
* model and update it when changes are made.
*/
public EditableSpotSceneImpl (EditableSpotSceneModel model)
{
_edelegate.setId(sceneId);
this(model, new DisplaySpotSceneImpl(model.spotSceneModel, null));
}
/**
* Creates an instance that will obtain data from the supplied scene
* model and update it when changes are made. It will delegate to the
* supplied display spot scene instead of creating its own delegate.
*/
public EditableSpotSceneImpl (
EditableSpotSceneModel model, DisplaySpotSceneImpl delegate)
{
super(model, delegate);
// keep track of these
_model = model.spotSceneModel;
_emodel = model;
_delegate = delegate;
// go through and replace the plain portals with editable portals
// (oh the machinations we have to go through for the lack of
// multiple inheritance)
List portals = _delegate.getPortals();
for (int i = 0; i < portals.size(); i++) {
EditablePortal port = dupePortal((Portal)portals.get(i));;
port.name = _emodel.portalNames[i];
port.targetSceneName = (String)_emodel.neighborNames.get(i);
port.targetPortalName = _emodel.targetPortalNames[i];
portals.set(i, port);
}
}
/**
* Constructs an editable portal with the same configuration as the
* supplied regular portal.
*/
protected EditablePortal dupePortal (Portal source)
{
EditablePortal port = new EditablePortal();
port.locationId = source.locationId;
port.x = source.x;
port.y = source.y;
port.orientation = source.orientation;
port.clusterIndex = source.clusterIndex;
port.targetSceneId = source.targetSceneId;
port.targetLocId = source.targetLocId;
return port;
}
// documentation inherited
public void setVersion (int version)
public int getDefaultEntranceId ()
{
_edelegate.setVersion(version);
return _delegate.getDefaultEntranceId();
}
// documentation inherited
public void setNeighborIds (int[] neighborIds)
public List getLocations ()
{
String errmsg = "Neighbor IDs can't be set directly in the " +
"EditableSpotScene because we need to know the associated " +
"location information to go along with our neighbor connections.";
throw new RuntimeException(errmsg);
return _delegate.getLocations();
}
// documentation inherited
public String getName ()
public List getPortals ()
{
return _edelegate.getName();
}
// documentation inherited
public void setName (String name)
{
_edelegate.setName(name);
}
// documentation inherited
public ArrayList getNeighborNames ()
{
String errmsg = "Neighbor names can't be fetched directly from the " +
"EditableSpotScene because we need to know the associated " +
"location information to go along with our neighbor connections.";
throw new RuntimeException(errmsg);
}
// documentation inherited
public void addNeighbor (String neighborName)
{
String errmsg = "Neighbors can't be added directly in the " +
"EditableSpotScene because we need to know the associated " +
"location information to go along with our neighbor connections.";
throw new RuntimeException(errmsg);
}
// documentation inherited
public boolean removeNeighbor (String neighborName)
{
String errmsg = "Neighbors can't be removed directly in the " +
"EditableSpotScene because we need to know the associated " +
"location information to go along with our neighbor connections.";
throw new RuntimeException(errmsg);
return _delegate.getPortals();
}
// documentation inherited
@@ -148,31 +126,15 @@ public class EditableSpotSceneImpl
// documentation inherited
public void addLocation (Location loc)
{
// add the location to the end of the location array
int lcount = _locations.length;
Location[] nlocs = new Location[lcount+1];
System.arraycopy(_locations, 0, nlocs, 0, lcount);
nlocs[lcount] = loc;
_locations = nlocs;
// add the location to the end of the location list
_delegate.getLocations().add(loc);
}
// documentation inherited
public void removeLocation (Location loc)
{
// obtain the index of this location
int lidx = ListUtil.indexOfEqual(_locations, loc);
if (lidx == -1) {
Log.warning("Can't remove location that isn't in our array " +
"[loc=" + loc + "].");
} else {
// create a new array minus this location
int lcount = _locations.length;
Location[] nlocs = new Location[lcount-1];
System.arraycopy(_locations, 0, nlocs, 0, lidx);
System.arraycopy(_locations, lidx+1, nlocs, lidx, lcount-lidx-1);
_locations = nlocs;
}
// remove the location from the list
_delegate.getLocations().remove(loc);
}
// documentation inherited
@@ -181,41 +143,18 @@ public class EditableSpotSceneImpl
// add it to the locations lists as well
addLocation(eport);
// now add it to the end of the _portals array
int pcount = _portals.length;
Portal[] nports = new Portal[pcount+1];
System.arraycopy(_portals, 0, nports, 0, pcount);
nports[pcount] = eport;
_portals = nports;
// now add it to the end of the _portals list
_delegate.getPortals().add(eport);
}
// documentation inherited
public void removePortal (EditablePortal eport)
{
// remove it from the locations array
// remove it from the locations list
removeLocation(eport);
// and remove it from the portals array
int pidx = ListUtil.indexOfEqual(_portals, eport);
if (pidx == -1) {
Log.warning("Can't remove portal that isn't in our array " +
"[port=" + eport + "].");
} else {
// create a new array minus this portal
int pcount = _portals.length;
Portal[] nports = new Portal[pcount-1];
System.arraycopy(_portals, 0, nports, 0, pidx);
System.arraycopy(_portals, pidx+1, nports, pidx, pcount-pidx-1);
_portals = nports;
}
}
// documentation inherited
public EditableSceneModel getSceneModel ()
{
flushToModel();
return _edelegate.getSceneModel();
// and remove it from the portals list
_delegate.getPortals().remove(eport);
}
// documentation inherited
@@ -232,8 +171,10 @@ public class EditableSpotSceneImpl
*/
protected void flushToModel ()
{
List locations = _delegate.getLocations();
// flush the locations
int lcount = _locations.length;
int lcount = locations.size();
_model.locationIds = new int[lcount];
_model.locationX = new int[lcount];
_model.locationY = new int[lcount];
@@ -241,7 +182,7 @@ public class EditableSpotSceneImpl
_model.locationClusters = new int[lcount];
for (int i = 0; i < lcount; i++) {
Location loc = _locations[i];
Location loc = (Location)locations.get(i);
_model.locationIds[i] = loc.locationId;
_model.locationX[i] = loc.x;
_model.locationY[i] = loc.y;
@@ -250,7 +191,8 @@ public class EditableSpotSceneImpl
}
// flush the portals
int pcount = _portals.length;
List portals = _delegate.getPortals();
int pcount = portals.size();
_model.portalIds = new int[pcount];
_model.neighborIds = new int[pcount];
_model.targetLocIds = new int[pcount];
@@ -259,7 +201,7 @@ public class EditableSpotSceneImpl
_emodel.targetPortalNames = new String[pcount];
for (int i = 0; i < pcount; i++) {
EditablePortal port = (EditablePortal)_portals[i];
EditablePortal port = (EditablePortal)portals.get(i);
_model.portalIds[i] = port.locationId;
_model.neighborIds[i] = port.targetSceneId;
_model.targetLocIds[i] = port.targetLocId;
@@ -269,15 +211,12 @@ public class EditableSpotSceneImpl
}
}
/** Our spot scene model. */
protected SpotSceneModel _model;
/** Our editable spot scene model. */
protected EditableSpotSceneModel _emodel;
/** We have to delegate some methods to this guy. */
protected EditableSceneImpl _edelegate;
/** A list of the editable locations (and portals) in this scene. */
protected ArrayList _elocations = new ArrayList();
/** A list of just the editable portals in this scene. */
protected ArrayList _eportals = new ArrayList();
/** Our display spot scene delegate. */
protected DisplaySpotSceneImpl _delegate;
}
@@ -1,8 +1,10 @@
//
// $Id: SpotSceneWriter.java,v 1.3 2001/12/05 04:45:13 mdb Exp $
// $Id: SpotSceneWriter.java,v 1.4 2001/12/05 08:45:06 mdb Exp $
package com.threerings.whirled.tools.spot.xml;
import java.util.Iterator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@@ -41,9 +43,9 @@ public class SpotSceneWriter extends SceneWriter
EditableSpotScene sscene = (EditableSpotScene)scene;
// write out the location info
Location[] locs = sscene.getLocations();
for (int i = 0; i < locs.length; i++) {
Location loc = locs[i];
Iterator iter = sscene.getLocations().iterator();
while (iter.hasNext()) {
Location loc = (Location)iter.next();
// skip portals as we'll get those on the next run
if (loc instanceof EditablePortal) {
continue;
@@ -57,9 +59,9 @@ public class SpotSceneWriter extends SceneWriter
}
// write out the portal info
Portal[] ports = sscene.getPortals();
for (int i = 0; i < ports.length; i++) {
EditablePortal port = (EditablePortal)ports[i];
iter = sscene.getPortals().iterator();
while (iter.hasNext()) {
EditablePortal port = (EditablePortal)iter.next();
AttributesImpl attrs = new AttributesImpl();
addSharedAttrs(attrs, port);
attrs.addAttribute("", "targetSceneName", "", "",
@@ -1,30 +1,19 @@
//
// $Id: EditableSceneImpl.java,v 1.4 2001/12/05 03:38:09 mdb Exp $
// $Id: EditableSceneImpl.java,v 1.5 2001/12/05 08:45:06 mdb Exp $
package com.threerings.whirled.tools;
import java.util.ArrayList;
import com.threerings.crowd.data.PlaceConfig;
import com.threerings.whirled.client.DisplaySceneImpl;
import com.threerings.whirled.data.SceneModel;
/**
* A basic implementation of the {@link EditableScene} interface.
*/
public class EditableSceneImpl
extends DisplaySceneImpl
implements EditableScene
public class EditableSceneImpl implements EditableScene
{
/**
* Creates an instance that will obtain data from the supplied scene
* model and update it when changes are made.
*/
public EditableSceneImpl (EditableSceneModel model)
{
super(model.sceneModel, null);
_emodel = model;
}
/**
* Creates an instance that will create and use a blank scene model.
*/
@@ -33,6 +22,52 @@ public class EditableSceneImpl
this(EditableSceneModel.blankSceneModel());
}
/**
* Creates an instance that will obtain data from the supplied scene
* model and update it when changes are made.
*/
public EditableSceneImpl (EditableSceneModel model)
{
this(model, new DisplaySceneImpl(model.sceneModel, null));
}
/**
* Creates an instance that will obtain data from the supplied scene
* model and update it when changes are made. It will delegate to the
* supplied display scene instead of creating its own delegate.
*/
public EditableSceneImpl (
EditableSceneModel model, DisplaySceneImpl delegate)
{
_model = model.sceneModel;
_emodel = model;
_delegate = delegate;
}
// documentation inherited
public int getId ()
{
return _delegate.getId();
}
// documentation inherited
public int getVersion ()
{
return _delegate.getVersion();
}
// documentation inherited
public int[] getNeighborIds ()
{
return _delegate.getNeighborIds();
}
// documentation inherited
public PlaceConfig getPlaceConfig ()
{
return _delegate.getPlaceConfig();
}
// documentation inherited
public void setId (int sceneId)
{
@@ -89,6 +124,12 @@ public class EditableSceneImpl
return _emodel;
}
/** A reference to our scene model. */
protected SceneModel _model;
/** A reference to our editable scene model. */
protected EditableSceneModel _emodel;
/** Our display scene delegate. */
protected DisplaySceneImpl _delegate;
}