|
// Resort Companion Data Manager
// Copyright (c) 2004 Wolf Logan
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
namespace org.CircleCross.ResortCompanion.Data {
/// <summary>
/// Represents a record of data in the database. Extended by specific record types.
/// </summary>
public abstract class RCDataRecord {
// field indices for the base data record
protected const int RCDATA_FIELD_SHAPE = 3;
protected const int RCDATA_FIELD_DESC = 2;
protected const int RCDATA_FIELD_NAME = 1;
protected const int RCDATA_FIELD_ID = 0;
/// <summary>
/// the string identifying the relation of this data table with its parent.
/// must be provided by derived classes
/// </summary>
protected string childRelation = null;
/// <summary>
/// the string identifying the relation of this data table with its children
/// must be provided by derived classes
/// </summary>
protected string parentRelation = null;
protected DataRow myRow;
protected RCDataRecord[] myChildren = null;
protected RCDataRecord myParent = null;
protected ShapeList mapShape = null;
/// <summary>
/// this record's Name field
/// </summary>
public string Name {
get {
return (string)this.myRow.ItemArray[RCDATA_FIELD_NAME];
}
}
/// <summary>
/// this record's Desc field
/// </summary>
public string Desc {
get {
return (string)this.myRow.ItemArray[RCDATA_FIELD_DESC];
}
}
/// <summary>
/// a list of the records contained by this record
/// </summary>
public RCDataRecord[] Children {
get {
// lazy instantiation of the child records
if(this.myChildren == null && this.childRelation != null) {
DataRow[] temp = this.myRow.GetChildRows(this.childRelation);
// call newChildRecords to create an appropriate container
this.myChildren = this.newChildRecords(temp.Length);
for(int i=0; i<temp.Length; i++) {
// call newChildRecord to create the apropriate child record type
this.myChildren[i] = this.newChildRecord(temp[i]);
}
}
return this.myChildren;
}
}
/// <summary>
/// the record that contains this record
/// </summary>
public RCDataRecord Parent {
get {
// lazy instantiation of the parent record
if(this.myParent == null && this.parentRelation != null) {
this.myParent = newParentRecord(this.myRow.GetParentRow(this.parentRelation));
}
return this.myParent;
}
}
/// <summary>
/// Draws the shape specified in the "Shape" field on the Graphics surface, in the style
/// indicated by theMode
/// </summary>
/// <param name="theSurface">the Graphics object to draw on</param>
/// <param name="theMode">the style in which to render the shape</param>
public void DrawShapes(Graphics theSurface, DrawingMode theMode) {
// lazy instantiation of the shape field
if(this.mapShape == null) {
this.mapShape = new ShapeList((string)this.myRow.ItemArray[RCDATA_FIELD_SHAPE]);
}
this.mapShape.DrawShapes(theSurface, theMode);
}
/// <summary>
/// requires extended types based on this type to define their own method for generating a parent.
/// this allows for type-safety and extended functionality in the lazy-instantiation accessors.
/// </summary>
/// <param name="row">the parent DataRow</param>
/// <returns>a properly typed parent</returns>
abstract protected RCDataRecord newParentRecord(DataRow row);
/// <summary>
/// requires extended types based on this type to define their own method for generating
/// an array of children.
/// this allows for type-safety and extended functionality in the lazy-instantiation accessors.
/// </summary>
/// <param name="count">the number of children to be created</param>
/// <returns>an properly typed, empty array of sufficient size</returns>
abstract protected RCDataRecord[] newChildRecords(int count);
/// <summary>
/// requires extended types based on this type to define their own method for generating a child.
/// this allows for type-safety and extended functionality in the lazy-instantiation accessors.
/// </summary>
/// <param name="row">the child DataRow</param>
/// <returns>a properly typed child</returns>
abstract protected RCDataRecord newChildRecord(DataRow row);
/// <summary>
/// basic constructor. stores the specified row in a private member.
/// </summary>
/// <param name="row">the DataRow to wrap</param>
protected RCDataRecord(DataRow row) {
this.myRow = row;
}
/// <summary>
/// uses the hashcode of the contained row as the wrapper's hashcode
/// </summary>
/// <returns>the hashcode of the contained row</returns>
public override int GetHashCode() {
return this.myRow.GetHashCode();
}
/// <summary>
/// determines equality by comparing the contained row
/// </summary>
/// <param name="obj">the object to compare to. must support a cast to RCDataRecord or
/// will throw an illegal cast exception</param>
/// <returns>"true" if the compared object's row is the same as this row</returns>
public override bool Equals(object obj) {
return (this.myRow == ((RCDataRecord)obj).myRow);
}
}
/// <summary>
/// wrapper class for Resort records
/// </summary>
public class ResortRecord: RCDataRecord {
public ComplexRecord[] Complexes {
get {
return (ComplexRecord[])this.Children;
}
}
override protected RCDataRecord newParentRecord(DataRow row) {
return null;
}
override protected RCDataRecord[] newChildRecords(int count) {
return new ComplexRecord[count];
}
override protected RCDataRecord newChildRecord(DataRow row) {
return ComplexRecord.Maker(row);
}
protected ResortRecord(DataRow row): base(row) {
this.childRelation = "Resort_Complex";
}
/// <summary>
/// static constructor for this class. required due to a seeming bug in the CLI
/// -- static initializers are not being called in this class when this class
/// is in a DLL
/// </summary>
static ResortRecord() {
ResortRecord.memo = new Hashtable();
}
/// <summary>
/// the cache of currently-instantiated records
/// </summary>
static protected Hashtable memo;
/// <summary>
/// the stand-in method of creating ResortRecords which can re-use existing record objects.
/// this saves memory and speeds up certain operations.
/// </summary>
/// <param name="row">the DataRow to reflect in a ResortRecord</param>
/// <returns>a ResortRecord object, either newly minted or retrieved from the cache</returns>
static public ResortRecord Maker(DataRow row) {
if(!(ResortRecord.memo.ContainsKey(row))) {
ResortRecord newRecord = new ResortRecord(row);
ResortRecord.memo[row] = newRecord;
}
return (ResortRecord)ResortRecord.memo[row];
}
}
/// <summary>
/// wrapper class for Complex records
/// </summary>
public class ComplexRecord: RCDataRecord {
public const int MAP_WIDTH = 400;
public const int MAP_HEIGHT = 400;
protected Bitmap mapImage = null;
public RegionRecord[] Regions {
get {
return (RegionRecord[])this.Children;
}
}
/// <summary>
/// The accessor for the bitmap representing this complex.
/// </summary>
public Bitmap MapImage {
get {
// lazy instantiation
if(this.mapImage == null) {
// create a full-sized map...
this.mapImage = new Bitmap(MAP_WIDTH, MAP_HEIGHT);
Graphics surface = Graphics.FromImage(this.mapImage);
// ...with a white background...
surface.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, MAP_WIDTH, MAP_HEIGHT));
// ...on it, draw this complex's own shape...
this.DrawShapes(surface, DrawingMode.Background);
// ...followed by all the children, in a darker color.
foreach(RegionRecord r in this.Regions) {
r.DrawShapes(surface, DrawingMode.Midground);
foreach(PlaceRecord p in r.Places) {
p.DrawShapes(surface, DrawingMode.Midground);
}
}
}
return this.mapImage;
}
}
override protected RCDataRecord newParentRecord(DataRow row) {
return ResortRecord.Maker(row);
}
override protected RCDataRecord[] newChildRecords(int count) {
return new RegionRecord[count];
}
override protected RCDataRecord newChildRecord(DataRow row) {
return RegionRecord.Maker(row);
}
protected ComplexRecord(DataRow row): base(row) {
this.childRelation = "Complex_Region";
this.parentRelation = "Resort_Complex";
}
/// <summary>
/// static constructor for this class. required due to a seeming bug in the CLI
/// -- static initializers are not being called in this class when this class
/// is in a DLL
/// </summary>
static ComplexRecord() {
ComplexRecord.memo = new Hashtable();
}
/// <summary>
/// the cache of currently-instantiated records
/// </summary>
static protected Hashtable memo;
/// <summary>
/// the stand-in method of creating ComplexRecords which can re-use existing record objects.
/// this saves memory and speeds up certain operations.
/// </summary>
/// <param name="row">the DataRow to reflect in a ComplexRecord</param>
/// <returns>a ComplexRecord object, either newly minted or retrieved from the cache</returns>
static public ComplexRecord Maker(DataRow row) {
if(!(ComplexRecord.memo.ContainsKey(row))) {
ComplexRecord newRecord = new ComplexRecord(row);
ComplexRecord.memo[row] = newRecord;
}
return (ComplexRecord)ComplexRecord.memo[row];
}
}
/// <summary>
/// wrapper class for Region records
/// </summary>
public class RegionRecord: RCDataRecord {
public ComplexRecord Complex {
get {
return (ComplexRecord)this.Parent;
}
}
public PlaceRecord[] Places {
get {
return (PlaceRecord[])this.Children;
}
}
override protected RCDataRecord newParentRecord(DataRow row) {
return ComplexRecord.Maker(row);
}
override protected RCDataRecord[] newChildRecords(int count) {
return new PlaceRecord[count];
}
override protected RCDataRecord newChildRecord(DataRow row) {
return PlaceRecord.Maker(row);
}
protected RegionRecord(DataRow row): base(row) {
this.childRelation = "Region_Place";
this.parentRelation = "Complex_Region";
}
/// <summary>
/// static constructor for this class. required due to a seeming bug in the CLI
/// -- static initializers are not being called in this class when this class
/// is in a DLL
/// </summary>
static RegionRecord() {
RegionRecord.memo = new Hashtable();
}
/// <summary>
/// the cache of currently-instantiated records
/// </summary>
static protected Hashtable memo;
/// <summary>
/// the stand-in method of creating RegionRecords which can re-use existing record objects.
/// this saves memory and speeds up certain operations.
/// </summary>
/// <param name="row">the DataRow to reflect in a RegionRecord</param>
/// <returns>a RegionRecord object, either newly minted or retrieved from the cache</returns>
static public RegionRecord Maker(DataRow row) {
if(!(RegionRecord.memo.ContainsKey(row))) {
RegionRecord newRecord = new RegionRecord(row);
RegionRecord.memo[row] = newRecord;
}
return (RegionRecord)RegionRecord.memo[row];
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.