Code walkthrough

This section contains code listings for the classes you need to create to build a simple Tiles document component:

TTile: header

TTile is declared in the file $TaligentRoot/TaligentSamples/Supported/Apps/TilesTutorial/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 &copy);
          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 &copy);
          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:

      // 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; }
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.

      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.

    static TGUIModelViewStationeryFor<TTilesModel, TTilesView> theStationery;
Now you're ready to use this stationery to create a Tiles document, as described in "Launching a document" on page 21.


[Contents] [Previous] [Next]
Click the icon to mail questions or corrections about this material to Taligent personnel.
Copyright©1995 Taligent,Inc. All rights reserved.

Generated with WebMaker