Code walkthrough

This section contains code listings for the new and modified classes you need to create to implement selections and commands:

TTilesSelection: header

TTilesSelection is declared in the file ./TilesTutorial/03.CommandsAndSelections/Tiles/TilesSelections.h:

      // Copyright (C) 1995 Taligent, Inc. All rights reserved.
      class TTilesSelection : public TGUIModelSelectionFor<TTilesModel> {
      public:
          TaligentTypeExtensionDeclarationsMacro(TTilesSelection)
          // Defines dynamic casting utilities
          DynamicCastDeclarationsMacro();
              
                              // Takes a reference to the model, used to initialize 
    // the base class. TTilesSelection(const TModelReference& theModel); virtual ~TTilesSelection(); TTilesSelection(const TTilesSelection& copy); virtual TStream& operator>>=(TStream& towhere) const; virtual TStream& operator<<=(TStream& fromwhere); TileIndex GetLowBound() const; TileIndex GetHighBound() const; TTile* GetTile(); // TGUIModelSelection For<AModel> overrides. virtual void DeselectAll (); virtual void SelectWholeModel (); virtual void SetUndefined (); // Creates a selection on a single tile. void SelectTile(TileIndex); // Support for modifying the color of selected tiles. void SetColor(TileIndex, const TRGBColor&); void SetColorAll(const TRGBColor&); TRGBColor GetColor(TileIndex whichTile) const; protected: TTilesSelection (); private: enum {kOriginalVersion}; // Address space-independent definition of the selected data. TileIndex fLowBound; TileIndex fHighBound; TTilesSelection& operator=(const TTilesSelection& copy) {return *this;} };

TTilesSelection: source

TTilesSelection is implemented in the file
./TilesTutorial/03.CommandsAndSelections/Tiles/TilesSelections.C:

More about accessing selections
Selections operate on the assumption that the caller takes care of locking the model before calling functions that access the model--so TTilesSelection functions can access the model without first creating an entry and locking the model.
Some TTilesSelection functions also verify that the selection isn't empty before trying to access any selected data. The base selection class provides the functions
IsEmpty and IsDefined for performing these checks. The framework also uses these functions--for example, to check whether menu items that require a non-empty selection should be enabled.
When the selection is set to empty with the DeselectAll function, the IsEmpty and IsDefined functions both return True. When the selection is set using the SetUndefined function, the IsEmpty function returns True
and the IsDefined function returns False.
You should use these functions to determine the state of the selection rather than relying on other information in the selection. For example, an empty TTilesSelection and a selection on the first tile both contain low and high bounds of 0. However, when the selection is empty, IsEmpty returns True; when the tile at index 0 is selected, IsEmpty returns False.

      // Copyright (C) 1995 Taligent, Inc. All rights reserved.
      // Matches calls in declaration.
      TaligentTypeExtensionMacro(TTilesSelection);
      DynamicCastDefinitionsMacroOne(TTilesSelection, TGUIModelSelectionFor<TTilesModel>);
      
      TTilesSelection::TTilesSelection(const TModelReference& theModel) :
          TGUIModelSelectionFor<TTilesModel>(theModel)
      {
          // This selection always starts out undefined.
          SetUndefined();
      }
      
      TTilesSelection::TTilesSelection() :
          TGUIModelSelectionFor<TTilesModel>()
      {
          // This selection always starts out undefined.
          SetUndefined();
      }
      
      TTilesSelection::TTilesSelection(const TTilesSelection& copy) :
          TGUIModelSelectionFor<TTilesModel>(copy),
          fLowBound(copy.fLowBound),
          fHighBound(copy.fHighBound)
      {}
      
      TTilesSelection::~TTilesSelection()
      {}
      
      TStream&
      TTilesSelection::operator>>=( TStream& toStream ) const
      {
          ::WriteVersion(toStream, kOriginalVersion);
          
          Streaming operators stream data in and out in the same order.
          TGUIModelSelectionFor<TTilesModel>::operator>>=(toStream);
          
          fLowBound >>= toStream;
          fHighBound >>= toStream;
          
          return toStream;
      }
      TStream&
      TTilesSelection::operator<<=( TStream& fromStream )
      {
          VersionInfo version = ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion);
          
          switch (version) {
          case kOriginalVersion: {
              TGUIModelSelectionFor<TTilesModel>::operator<<=(fromStream);
              fLowBound <<= fromStream;
              fHighBound <<= fromStream;
              break;
              }
          default:
              throw TInvalidVersionError();
          }
          
          return fromStream;
      }
      
      // Sets all selected tiles to the specified color. Caller doesn't need to know whether
      // a single tile, all tiles, or no tiles are selected.
      void 
      TTilesSelection::SetColorAll (const TRGBColor& color)
      {
          TileIndex i;
          if (!IsEmpty()) {
              TTilesModel* model = GetModelForWriting();
      
              for (i = fLowBound; i <= fHighBound; i++) {
                  model->GetTileForWriting(i)->SetColor(color);
              }
          }
      }
      
      // Sets a single tile to the specified color. 
      // The tile must be within the range of this selection.
      void 
      TTilesSelection::SetColor (TileIndex whichTile, const TRGBColor& color)
      {
          if (!IsEmpty()) {
              if (whichTile >= fLowBound && whichTile <= fHighBound) {
                  GetModelForWriting()->GetTileForWriting(whichTile)->SetColor(color);
              }
              else {
                  ::qprintf ("TTilesSelection::SetColor(): illegalTile\n");
              }
          }
      }
      
      // Returns the color of a specific tile, which must be within the range of this selection.
      TRGBColor 
      TTilesSelection::GetColor (TileIndex whichTile) const
      {
          if (!IsEmpty() && whichTile >= fLowBound && whichTile <= fHighBound) {
              return GetModelForReading()->GetTileForReading(whichTile)->GetColor();
          }
          else {
              ::qprintf ("TTilesSelection::GetColor(): illegalTile\n");
              return TRGBColor(0,0,0);
          }
      }
      
      TileIndex
      TTilesSelection::GetLowBound () const
      {
          return fLowBound;
      }
      
      TileIndex
      TTilesSelection::GetHighBound () const
      {
          return fHighBound;
      }
      
      // Called when a user chooses the "Select All" menu item. 
      // Must call the base class function.
      void 
      TTilesSelection::SelectWholeModel()
      {
          TGUIModelSelectionFor<TTilesModel>::SelectWholeModel();
          
          fLowBound = 0;
          fHighBound = GetModelForReading()->GetNumTiles() - 1;
          if (GetState() == kEmpty && fHighBound != -1) SetState(kNotEmpty);
      }
      
      void 
      TTilesSelection::DeselectAll()
      {
          // After calling the base class function, IsEmpty returns True.
          TGUIModelSelectionFor<TTilesModel>::DeselectAll();
          fLowBound = 0;
          fHighBound = 0;
      }
      
      void 
      TTilesSelection::SetUndefined()
      {
          // After calling the base class function, IsDefined returns False.
          TGUIModelSelectionFor<TTilesModel>::SetUndefined();
          fLowBound = 0;
          fHighBound = 0;
      }
      
      void 
      TTilesSelection::SelectTile(TileIndex tileIndex)
      {
          TileIndex maxIndex = GetModelForReading()->GetNumTiles() - 1;
          
          // Verifies that the selection is valid.
          if (tileIndex >= 0 && tileIndex <= maxIndex) {
              fLowBound = tileIndex;
              fHighBound = tileIndex;
           // After this call, IsEmpty returns False and IsDefined returns True.
              SetState (kNotEmpty);
          }
      
          else {
              // If the selection is invalid, sets it to empty.
              DeselectAll(); 
          }
      }

Command binding

For the command binding, Tiles uses the Presentation framework class template
TGUIDocumentComponentCommandBindingTo<TTilesSelection> as is.

This typedef statement is in the file
./TilesTutorial/03.CommandsAndSelections/Tiles/TilesCommands.h:

    typedef TGUIDocumentComponentCommandBindingTo<TTilesSelection> TTilesCommandBinding;
TGUIDocumentComponentCommandBindingTo<TTilesSelection> requires a TGUIBundle when it is constructed, as you'll see when one is constructed in TTilesView::MouseDown.

TChangeColorCommand: header

TChangeColorCommand is declared in the file
./TilesTutorial/03.CommandsAndSelections/Tiles/TileCommands.h:

      // Copyright (C) 1995 Taligent, Inc. All rights reserved.
      class TChangeColorCommand : public TCommandOn<TTilesSelection> {
      public:
          TaligentTypeExtensionDeclarationsMacro(TChangeColorCommand)
      
                               // Take the color to apply to the target selection..
                               TChangeColorCommand (const TRGBColor& newColor);
      
                               TChangeColorCommand ();
                               TChangeColorCommand(const TChangeColorCommand &copy);
          virtual              ~TChangeColorCommand ();
          TChangeColorCommand& operator=(const TChangeColorCommand& copy);
          virtualTStream&      operator>>=(TStream& toStream) const;
          virtualTStream&      operator<<=(TStream& fromStream);
      
      protected:
          // TCommandOn<ATarget> overrides.
          virtual void         HandleDoBegin(TTilesSelection& target);
          virtual void         HandleUndo(TTilesSelection& target);
          virtual void         HandleRedo(TTilesSelection& target);
              
      private:
          enum            {kOriginalVersion};
              
          // Color to apply to target selection.
          TRGBColor       fNewColor;
      
          // Number of tiles in selection.
          TileIndex       fNumTiles;
      
          // Allocates space to store old colors.
          TRGBColor*      fOldColor;
      };

TChangeColorCommand: source

TChangeColorCommand is implemented in the file
./TilesTutorial/03.CommandsAndSelections/Tiles/TileCommands.C:

      // Copyright (C) 1995 Taligent, Inc. All rights reserved.
      TaligentTypeExtensionMacro(TChangeColorCommand);
      
      // You need to specify kSerialUndo in the base class constructor. 
      // The default is kCantUndo.
      TChangeColorCommand::TChangeColorCommand(const TRGBColor& newColor) :
          TCommandOn<TTilesSelection>(TCommandOn<TTilesSelection>::kSerialUndo),
          fNewColor(newColor), fNumTiles(0), fOldColor(NIL)
      {}
      
      TChangeColorCommand::TChangeColorCommand() :
          TCommandOn<TTilesSelection>(TCommandOn<TTilesSelection>::kSerialUndo),
          fNewColor(TRGBColor(0,0,0)), fNumTiles(0), fOldColor(NIL)
      {}
      
      TChangeColorCommand::TChangeColorCommand(const TChangeColorCommand &copy) :
          TCommandOn<TTilesSelection>(copy), fNewColor(copy.fNewColor),
          fNumTiles(copy.fNumTiles)
      {
          // Allocates space for the old colors and copies them.
          fOldColor = new TRGBColor[fNumTiles]; 
          for (short i = 0; i < fNumTiles; i++) {
              fOldColor[i] = copy.fOldColor[i];
          }
      }
      
      TChangeColorCommand::~TChangeColorCommand()
      {
          // Deletes the array of old colors.
          delete [] fOldColor;
      }
          
      TStream&
      TChangeColorCommand::operator>>=(TStream& toStream) const
      {
          ::WriteVersion(toStream, kOriginalVersion);
          TCommandOn<TTilesSelection>::operator>>=(toStream);
          
          fNewColor >>= toStream;
          fNumTiles >>= toStream;
          for (short i = 0; i < fNumTiles; i++) {
              fOldColor[i] >>= toStream;
          }
          return toStream;
      }
      
      TStream&
      TChangeColorCommand::operator<<=(TStream& fromStream)
      {
          VersionInfo version = ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion);
          
          switch (version) {
          case kOriginalVersion: {
              short temp;
              TCommandOn<TTilesSelection>::operator<<=(fromStream);
              delete [] fOldColor;
              fNewColor <<= fromStream;
              fNumTiles <<= fromStream;
                  
              fOldColor = new TRGBColor[fNumTiles];
              for (short i = 0; i < fNumTiles; i++) {
                  fOldColor[i] <<= fromStream;
              }
              break;
              }
          default:
              throw TInvalidVersionError();
          }
          return fromStream;
      }
      
      // This function executes the command.
      void
      TChangeColorCommand::HandleDoBegin(TTilesSelection& target)
      {   
          TileIndex i, lowBound;
          lowBound = target.GetLowBound();
          fNumTiles = target.GetHighBound() - lowBound + 1;
      
          // Allocates space to store old colors.
          fOldColor = new TRGBColor[fNumTiles];
      
          // Saves old colors for undo.
          for (i=0; i < fNumTiles; i++) {
              fOldColor[i] = target.GetColor(i+lowBound);
          }
      
          // Changes color of all selected tiles.
          target.SetColorAll (fNewColor);
      }
          
      // This function changes the color of the selected tiles back to the old colors
      // stored by HandleDoBegin.
      void
      TChangeColorCommand::HandleUndo(TTilesSelection& target)
      {
          TileIndex i, lowBound;
          
          lowBound = target.GetLowBound();
              
          for (i=0; i < fNumTiles; i++) {
              target.SetColor (i+lowBound, fOldColor[i]);
          }
      }
          
      // This function redoes an undone command. 
      // HandleDoBegin has already saved the old colors.
      void
      TChangeColorCommand::HandleRedo(TTilesSelection& target)
      {
          target.SetColorAll (fNewColor);
      }

TTilesModel:: CreateSelection

The modified implementation of the TTilesModel::CreateSelection function is in the file ./TilesTutorial/03.CommandsAndSelections/Tiles/TilesModel.C. New and modified code is shown in bold:

      // Copyright (C) 1995 Taligent, Inc. All rights reserved.
      TModelSelection*
      TTilesModel::CreateSelection() const
      {
          // Creates a new selection and sets it to the default selection for this model.
          TTilesSelection* selection = new TTilesSelection(TModelReference(*this));
          selection->SelectDefault();
          return selection;
      }

TTilesView::MouseDown

The modified implementation of the TTilesView::MouseDown function is in the file ./TilesTutorial/03.CommandsAndSelections/Tiles/TilesView.C. New and modified code is shown in bold:

      // Copyright (C) 1995 Taligent, Inc. All rights reserved.
      bool
      TTilesView::MouseDown (TMouseDownEvent& mouseDownEvent)
      {
          TileIndex whichTile;
          // Allocates a command binding and color.
          TRGBColor newColor;
          TTilesCommandBinding* commandBinding = NIL;
          
          TGPoint mousePoint = mouseDownEvent.GetEventPosition();
      
          {
              const TModelPointerTo<TTilesModel> model(GetModelReference());
              
              for (whichTile = model->GetNumTiles() - 1; whichTile >= 0; whichTile--) {
                  if (model->GetTileForReading(whichTile)->ContainsPoint(mousePoint)) {
                      break;
                  }
              }
              
              // If a tile was clicked on:
              if (whichTile >= 0) {
      
                  // Creates a selection specifying the clicked-on tile.
                  TTilesSelection* selection = (TTilesSelection*) model->CreateSelection ();
                  selection->SelectTile (whichTile);
                  
                  // Gets the color of the selected tile and 
                  // determines the color to change it to.
                  TRGBColor currentColor = model->GetTileForReading(whichTile)->GetColor() ;
      
                  if (currentColor == TRGBColor(1,0,0))
                      newColor = TRGBColor(0,1,0);
                  else if (currentColor == TRGBColor(0,1,0))
                      newColor = TRGBColor(0,0,1);
                  else if (currentColor == TRGBColor(0,0,1))
                      newColor = TRGBColor(1,0,0);
      
      
                  // Creates a command with the new color.
                  TChangeColorCommand* command = new TChangeColorCommand (newColor);
      
      
                  // Binds the command to the selection.
                  commandBinding = new TTilesCommandBinding(command, selection,
                                      *GetGUIBundle(), TStandardText("Change Color"));
              }
          }
      
          // Requests the document to adopt.
          if (commandBinding) AdoptAndDo(commandBinding);
      
          return TRUE;
      }

[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