Click here to Skip to main content
15,893,381 members
Articles / Mobile Apps / Windows Mobile

Resort Companion

Rate me:
Please Sign up or sign in to vote.
3.95/5 (20 votes)
2 Jun 2004CPOL7 min read 55.2K   178   18  
Presenting the Resort Companion, a data-navigation application for vacation resorts
// 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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions