01.ModelView/
Tiles/TilesModel.h
:
// Copyright (C) 1995 Taligent, Inc. All rights reserved. class TTile { public: // Required macro call. TaligentTypeExtensionDeclarationsMacro(TTile) // EType defines the kinds of tiles. enum EType {kRock, kPaper, kScissors}; TTile (EType, TRGBColor, TGPoint position, TGPoint size); // Required functions for classes using TaligentTypeExtensions. TTile(); TTile(const TTile ©); virtual ~TTile(); TTile& operator=(const TTile& rhs); virtualTStream& operator>>=(TStream& towhere) const; virtualTStream& operator<<=(TStream& fromwhere); // Data accessors. Get functions should be const. EType GetType() const; void SetType(EType type); TRGBColor GetColor() const; void SetColor(TRGBColor color); TGPoint GetPosition() const; void SetPosition(const TGPoint& point); TGPoint GetSize() const; void SetSize(const TGPoint& size); private: // Data describing the tile. fBounds indicates both size and position. enum {kOriginalVersion}; EType fType; TRGBColor fColor; TGRect fBounds; };
Versioning | ||
The version number is used by the streaming operators to determine what version of a class a particular object was instantiated from. This allows you to stream the object in properly and to make any adjustments to data in older versions to |
make the object usable with an upgraded version of a class. The classes you see created in this tutorial are mainly original versions of a class. However, in Step 7 you'll see how to support two versions of TTilesModel. |
Your streaming operators must be able to read in all older versions of an object. This ensures that persistent objects created with an older version of a class are still usable when the class is upgraded. |
TTile: source
TTile is implemented in the file ./TilesTutorial/01.ModelView/Tiles/TilesModel.C
:
// Copyright (C) 1995 Taligent, Inc. All rights reserved.
// Matches call in the declaration. This defines the necessary utilities.
TaligentTypeExtensionMacro(TTile);
TTile::TTile ()
: fType(kRock), fColor(TRGBColor(1,0,0)),
fBounds(TGPoint::kOrigin, TGPoint::kOrigin)
{}
TTile::TTile (EType type, TRGBColor color, TGPoint position, TGPoint size)
: fType(type), fColor(color)
{
// Uses a TGRect to store both the size and position.
fBounds.Set(position, position+size);
}
TTile::TTile (const TTile& copy) :
fType(copy.fType), fColor(copy.fColor), fBounds(copy.fBounds)
{}
TTile::~TTile ()
{}
TStream&
TTile::operator>>=(TStream& toStream) const
{
// Streams out the version number, then the tile data.
// You need to cast the enum value to a short before streaming.
::WriteVersion(toStream, kOriginalVersion);
(short) fType >>= toStream;
fColor >>= toStream;
fBounds >>= toStream;
return toStream;
}
TStream&
TTile::operator<<=(TStream& fromStream)
{
// Streams in the version number, then streams in the data as appropriate for that version
// (currently there is only one version).
VersionInfo version = ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion);
switch (version) {
case kOriginalVersion: {
short type;
type <<= fromStream;
fType = (EType) type;
fColor <<= fromStream;
fBounds <<= fromStream;
break;
}
// Support for subsequent versions would go here.
default:
throw TInvalidVersionError();
}
return fromStream;
}
TTile::EType
// Getter functions should all be const. You should only modify data with setter functions.
TTile::GetType() const
{
return fType;
}
void
TTile::SetType(EType type)
{
fType = type;
}
TRGBColor
TTile::GetColor() const
{
return fColor;
}
void
TTile::SetColor(TRGBColor color)
{
fColor = color;
}
TGPoint
TTile::GetPosition () const
{
// The position of the tile within the view is the top left corner of the rectangle.
return fBounds.GetTopLeft();
}
void
TTile::SetPosition (const TGPoint& point)
{
fBounds.Set(point, point+fBounds.GetSize());
}
TGPoint
TTile::GetSize () const
{
return fBounds.GetSize();
}
void
TTile::SetSize (const TGPoint& size)
{
TGPoint position = fBounds.GetTopLeft();
fBounds.Set(position, position+size);
}
TTile&
TTile::operator=(const TTile& rhs)
{
// The assignment operator should always check for assignment of the object to itself.
if (this != &rhs) {
fType = rhs.fType;
fColor = rhs.fColor;
fBounds = rhs.fBounds;
}
return *this;
}
TTilesModel: header
TTilesModel is declared in the file
./TilesTutorial/01.ModelView/Tiles/TilesModel.h
:
// Copyright (C) 1995 Taligent, Inc. All rights reserved.
class TTilesModel : public TModel {
public:
// Required macro call declares TaligentTypeExtensions and dynamic cast functions.
ModelDeclarationsMacro(TTilesModel);
TTilesModel ();
TTilesModel (const TTilesModel ©);
virtual ~TTilesModel ();
virtualTStream& operator>>= (TStream& towhere) const;
virtualTStream& operator<<= (TStream& fromwhere);
// Creates a default selection.
virtual TModelSelection* CreateSelection () const;
// Functions for accessing data in the model.
TileIndex GetNumTiles () const;
const TTile* GetTileForReading (TileIndex whichTile) const;
TTile* GetTileForWriting (TileIndex whichTile);
// Functions for adding and removing tiles.
TileIndex AdoptTile (TTile* tileToAdopt);
TTile* OrphanTile (TileIndex index);
private:
enum {kOriginalVersion};
// Stores the tiles in a growable array.
TArrayOf<TTile> fTiles;
TTilesModel& operator= (const TTilesModel& model) {return *this;}
};
TTilesModel: source
TTilesModel is declared in the file
./TilesTutorial/01.ModelView/Tiles/TilesModel.h
:
// Copyright (C) 1995 Taligent, Inc. All rights reserved.
// Matches call in declaration. Pass the class, version, and base class.
ModelDefinitionsMacroOne(TTilesModel, kOriginalVersion, TModel);
// Initializes the model with one tile of each type.
TTilesModel::TTilesModel()
: TModel(), fTiles(0, new TMonomorphicStreamer<TTile>, 0)
{
AdoptTile(new TTile(TTile::kRock, TRGBColor(1,0,0), TGPoint(10,10),
TGPoint(50,50)));
AdoptTile(new TTile(TTile::kPaper, TRGBColor(0,1,0), TGPoint(70,10),
TGPoint(50,50)));
AdoptTile(new TTile (TTile::kScissors, TRGBColor(0,0,1), TGPoint(130,10),
TGPoint(50,50)));
// Allows array to grow as tiles are added.
fTiles.SetAutoGrowFlag(TRUE);
}
TTilesModel::TTilesModel(const TTilesModel& other)
: TModel(other), fTiles(0, new TMonomorphicStreamer<TTile>, 0)
{
// Creates a copy of each tile and has the clone adopt it.
for (int i = 0; i < other.fTiles.Count(); i++) {
AdoptTile(new TTile(*other.fTiles.At(i)));
}
}
TTilesModel::~TTilesModel()
{
// Deletes each tile in the array
fTiles.DeleteAll();
}
TStream&
TTilesModel::operator>>=(TStream& toStream) const
{
// WriteVersion streams out a specific version.
::WriteVersion(toStream, kOriginalVersion);
TModel::operator>>=(toStream);
fTiles >>= toStream;
return toStream;
}
TStream&
TTilesModel::operator<<=(TStream& fromStream)
{
// ReadVersion takes a low and high bound indicating the range of versions this operator can stream in.
// It throws an exception if the object in fromStream is outside this range.
VersionInfo version = ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion);
switch (version) {
case kOriginalVersion: {
TModel::operator<<=(fromStream);
fTiles.DeleteAll();
fTiles <<= fromStream;
break;
}
default:
throw TInvalidVersionError();
}
return fromStream;
}
TModelSelection*
TTilesModel::CreateSelection() const
{
// Returns a "dummy" selection for this model.
return new TGUIModelSelectionFor<TTilesModel>;
}
TileIndex
TTilesModel::GetNumTiles() const
{
return fTiles.Count();
}
// GetTileForWriting and GetTileForReading return a pointer to the specified tile.
// The model must be locked before these functions are called and remain
// locked as long as the returned pointer is in use.
TTile*
TTilesModel::GetTileForWriting(TileIndex whichTile)
{
return (TTile*) GetTileForReading (whichTile);
}
const TTile*
TTilesModel::GetTileForReading (TileIndex whichTile) const
{
const TTile* tile=0;
if (whichTile >= 0 && whichTile < fTiles.Count()) {
tile = fTiles.At(whichTile);
}
else {
::qprintf("TTilesModel::GetTileForWriting: Illegal tile chosen from model");
}
return tile;
}
// Takes ownership for the tile passed in. The caller can still access the tile
// using the returned index.
TileIndex
TTilesModel::AdoptTile(TTile* tileToAdopt)
{
TileIndex index = -1;
if (tileToAdopt != 0) {
index = fTiles.Count();
fTiles.AtPut(index, tileToAdopt);
}
return index;
}
// Gives ownership of the specified tile to the caller.
TTile*
TTilesModel::OrphanTile(TileIndex index)
{
TTile* tile = fTiles.At(index);
fTiles.Compress(index, 1);
return tile;
}
TTilesView: header
TTilesView is declared in the file
./TilesTutorial/01.ModelView/Tiles/TilesView.h
:
// Copyright (C) 1995 Taligent, Inc. All rights reserved.
class TTilesView : public TDocumentComponentView {
public:
// Required macro. Defines versioning utilities.
VersionDeclarationsMacro(TTilesView);
// Constructor requires a TGUIBundle.
TTilesView(TGUIBundle* b);
virtual ~TTilesView();
protected:
TTilesView();
TTilesView(const TTilesView& copy);
// Provides initialization and finalization routines.
virtual void HandleAfterConnectionToViewRoot();
virtual void HandleBeforeDisconnectionFromViewRoot();
// Primary function for any content view.
virtual void DrawContents(TGrafPort& port) const;
void DrawTile(TGrafPort& port, const TTile* tile) const;
// Builds map between model data and drawable objects.
void BuildTilesGraphicsMapToModel();
void DestroyTilesGraphicsMapToModel();
private:
enum {kOriginalVersion};
// Stores the map of graphics for rendering.
enum {kNumTilesGraphics=3};
MGraphic* fTilesGraphics[kNumTilesGraphics];
};
TTilesView: source
TTilesView is implemented in the file
./TilesTutorial/01.ModelView/Tiles/TileView.C:
NOTE
See the online class and member function documentation or 2D and 3D Graphics for detailed information on the rendering functions used in the TTilesView DrawContents and DrawTile functions. // Copyright (C) 1995 Taligent, Inc. All rights reserved.
// Matches call in declaration.
VersionDefinitionsMacro(TTilesView, kOriginalVersion);
// Primary constructor for the view.
TTilesView::TTilesView(TGUIBundle* bundle)
: TDocumentComponentView(bundle)
{}
TTilesView::TTilesView()
: TDocumentComponentView()
{}
TTilesView::TTilesView(const TTilesView& copy)
: TDocumentComponentView(copy)
{}
TTilesView::~TTilesView()
{}
// Must call base class function. Builds the map and sets the default size.
// Any other initialization code would go here.
void
TTilesView::HandleAfterConnectionToViewRoot()
{
TDocumentComponentView::HandleAfterConnectionToViewRoot ();
BuildTilesGraphicsMapToModel();
SetAllocatedArea(TGArea(TGRect(TGPoint(0,0), TGPoint(200, 100))));
}
// Must call base class function. Destroys the map.
// Any other clean-up code would go here.
void
TTilesView::HandleBeforeDisconnectionFromViewRoot()
{
TDocumentComponentView::HandleBeforeDisconnectionFromViewRoot();
DestroyTilesGraphicsMapToModel();
}
void
TTilesView::DrawContents(TGrafPort& port) const
{
// Creates a smart pointer for read-only access.
const TModelPointerTo<TTilesModel> model(GetModelReference());
// Gets the area of the view and draws a background.
TGArea area;
GetBounds(area);
TGrafBundle whitebg (new TColorPaint(TRGBColor(.9,1,1)), TGrafBundle::kFill);
port.Draw (area, whitebg);
// Passes each tile to DrawTile to be drawn individually.
// The smart pointer is destroyed and the model unlocked when the function finishes.
int numTiles = model->GetNumTiles();
for (int i = 0; i < numTiles; i++) {
const TTile* tile = model->GetTileForReading(i);
DrawTile(port, tile);
}
}
void
TTilesView::DrawTile (TGrafPort& port, const TTile* tile) const
{
// Creates a graf bundle with the drawing attributes.
TGrafBundle* bundle = new TGrafBundle(new TColorPaint(tile->GetColor()),
new TColorPaint(TColorPaint::GetBlack()), TGrafBundle::kFill);
// Gets a polymorphic copy of the MGraphic.
MGraphic* tileGraphic = ::CopyPointer(fTilesGraphics[tile->GetType()]);
tileGraphic->ScaleBy(tile->GetSize());
tileGraphic->TranslateBy(tile->GetPosition());
// Requests the graphic to adopt the drawing attributes and draw itself.
tileGraphic->AdoptBundle(bundle);
tileGraphic->Draw(port);
delete tileGraphic;
}
void
TTilesView::BuildTilesGraphicsMapToModel ()
{
// Creates an MGraphic to represent each type of tile, normalized to 1.0
TEllipse* circle = new TEllipse(TGRect(TGPoint::kOrigin, TGPoint(1.0, 1.0)));
TPolygon* square = new TPolygon(TGRect(TGPoint(0.0, 0.0), TGPoint(1.0, 1.0)));
TGPointArray pointArray (3);
pointArray.SetPoint(0, TGPoint(0.5, 0.0));
pointArray.SetPoint(1, TGPoint(1.0, 1.0));
pointArray.SetPoint(2, TGPoint(0.0, 1.0));
TPolygon* triangle = new TPolygon(TGPolygon(pointArray));
// Stores each graphic in the array.
fTilesGraphics[TTile::kRock] = circle;
fTilesGraphics[TTile::kPaper] = square;
fTilesGraphics[TTile::kScissors] = triangle;
}
void
TTilesView::DestroyTilesGraphicsMapToModel ()
{
// Deletes each MGraphic.
delete fTilesGraphics[TTile::kRock];
delete fTilesGraphics[TTile::kPaper];
delete fTilesGraphics[TTile::kScissors];
}
Instantiating the stationery template
Instantiating the template into a stationery class requires only a single line of code. This line is in the file ./TilesTutorial/01.ModelView/Tiles/TilesView.C
.
Now you're ready to use this stationery to create a Tiles document, as described in "Launching a document" on page 21.static TGUIModelViewStationeryFor<TTilesModel, TTilesView> theStationery;
[Contents]
[Previous]
[Next]
Click the icon to mail questions or corrections about this material to Taligent personnel.
Generated with WebMaker