// $Revision: 1.1 $ // Copyright (C) 1994, 1995 Taligent, Inc. All rights reserved. // TilesSelections.C #ifndef TaligentSample_TILESSELECTIONS #include "TilesSelections.h" #endif // This macro call matches a macro call to TaligentTypeExtensionDeclarationsMacro // in the TTilesSelection class declaration. This macro defines the // TaligentTypeExtension utility functions. kOriginal version is the version // level of the selection. TaligentTypeExtensionMacro(TTilesSelection); // This macro call matches a macro call to DynamicCastDeclarationsMacro // in the TTilesSelection class declaration. This macro defines the // dynamic cast utility functions. Use DynamicCastDefinitionsMacroTwo // if there are two base classes, etc. DynamicCastDefinitionsMacroOne(TTilesSelection, TGUIEmbedderModelSelectionFor); // constructor used to create a TTilesSelection in this program TTilesSelection::TTilesSelection(const TModelReference& theModel) : TGUIEmbedderModelSelectionFor(theModel) { // This selection always starts out undefined SetUndefined(); } // default constructor, required by Taligent Type Extensions TTilesSelection::TTilesSelection() : TGUIEmbedderModelSelectionFor() { // This selection always starts out undefined SetUndefined(); } // copy constructor, required by Taligent Type Extensions TTilesSelection::TTilesSelection(const TTilesSelection& copy) : TGUIEmbedderModelSelectionFor(copy), fLowBound(copy.fLowBound), fHighBound(copy.fHighBound) {} TTilesSelection::~TTilesSelection() {} // Stream out operatorTStream&, required by Taligent Type Extensions // Must match operator<<=. Should stream out a version level. TStream& TTilesSelection::operator>>=( TStream& toStream ) const { // Place the version number onto the stream ::WriteVersion(toStream, kOriginalVersion); // Stream out the base class data TGUIEmbedderModelSelectionFor::operator>>=(toStream); // Stream out TTilesSelection data fLowBound >>= toStream; fHighBound >>= toStream; return toStream; } // Stream in operator, required by Taligent Type Extensions // Must match operator>>=. Should be able to handle different versions. TStream& TTilesSelection::operator<<=( TStream& fromStream ) { // Read in the version VersionInfo version = ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion); switch (version) { case kOriginalVersion: { TGUIEmbedderModelSelectionFor::operator<<=(fromStream); fLowBound <<= fromStream; fHighBound <<= fromStream; break; } // New versions would be added here to support changes in the TTilesSelection default: throw TInvalidVersionError(); } return fromStream; } // SetColorAll will set the color of all TTiles in the selection to the color parameter. // The caller does not worry whether the selection is on a single tile, on the whole model // or if the selection is empty. void TTilesSelection::SetColorAll (const TRGBColor& color) { TileIndex i; if (!IsEmpty()) { // Selections assume that the caller has taken care of locking the model. TTilesModel* model = GetModelForWriting(); for (i = fLowBound; i <= fHighBound; i++) { model->GetTileForWriting(i)->SetColor(color); } } } // SetColor allows the caller to set the color of a specific TTile in the selection. // SetColor does not allow modification of TTiles outside of the range of the selection. // If the selection is empty, nothing happens. void TTilesSelection::SetColor (TileIndex whichTile, const TRGBColor& color) { if (!IsEmpty()) { if (whichTile >= fLowBound && whichTile <= fHighBound) { // Selections assume that the caller has taken care of locking the model. GetModelForWriting()->GetTileForWriting(whichTile)->SetColor(color); } else { // Throw an exception? ::qprintf ("TTilesSelection::SetColor(): illegalTile\n"); } } } // GetColor returns the color of a specific TTile in the selection. TRGBColor TTilesSelection::GetColor (TileIndex whichTile) const { if (!IsEmpty() && whichTile >= fLowBound && whichTile <= fHighBound) { // Selections assume that the caller has taken care of locking the model. return GetModelForReading()->GetTileForReading(whichTile)->GetColor(); } else { // Throw an exception? ::qprintf ("TTilesSelection::GetColor(): illegalTile\n"); return TRGBColor(0,0,0); } } // SetTextAll will set the Text of all TTiles in the selection to the Text parameter. // The caller does not worry whether the selection is on a single tile, on the whole model // or if the selection is empty. void TTilesSelection::SetTextAll (const TStandardText& Text) { TileIndex i; if (!IsEmpty()) { // Selections assume that the caller has taken care of locking the model. TTilesModel* model = GetModelForWriting(); for (i = fLowBound; i <= fHighBound; i++) { model->GetTileForWriting(i)->SetText(Text); } } } // SetText allows the caller to set the Text of a specific TTile in the selection. // SetText does not allow modification of TTiles outside of the range of the selection. // If the selection is empty, nothing happens. void TTilesSelection::SetText (TileIndex whichTile, const TStandardText& Text) { if (!IsEmpty()) { if (whichTile >= fLowBound && whichTile <= fHighBound) { // Selections assume that the caller has taken care of locking the model. GetModelForWriting()->GetTileForWriting(whichTile)->SetText(Text); } else { // Throw an exception? ::qprintf ("TTilesSelection::SetText(): illegalTile\n"); } } } // GetText returns the Text of a specific TTile in the selection. TStandardText TTilesSelection::GetText (TileIndex whichTile) const { if (!IsEmpty() && whichTile >= fLowBound && whichTile <= fHighBound) { // Selections assume that the caller has taken care of locking the model. return GetModelForReading()->GetTileForReading(whichTile)->GetText(); } else { // Throw an exception? ::qprintf ("TTilesSelection::GetText(): illegalTile\n"); return TStandardText(""); } } // Set the position of the selected tile. Works only if one TTile is selected. void TTilesSelection::SetPosition (const TGPoint& point) { // Can only work on a single tile selection if (!IsEmpty() && fLowBound == fHighBound) { // Selections assume that the caller has taken care of locking the model. GetModelForWriting()->GetTileForWriting(fLowBound)->SetPosition(point); } } // Get the position of the selected tile. Works only if one TTile is selected. TGPoint TTilesSelection::GetPosition () { // Can only work on a single tile selection if (!IsEmpty() && fLowBound == fHighBound) { // Selections assume that the caller has taken care of locking the model. return GetModelForReading()->GetTileForReading(fLowBound)->GetPosition(); } else { return TGPoint(0,0); } } TileIndex TTilesSelection::GetLowBound () const { return fLowBound; } TileIndex TTilesSelection::GetHighBound () const { return fHighBound; } // This function is called by the Framework when the user chooses "Select All" // and is also used whenever a whole model selection is needed. // The base class function SelectWholeModel() must be called. void TTilesSelection::SelectWholeModel() { //have to set the state correctly on select whole model. TGUIEmbedderModelSelectionFor::SelectWholeModel(); // Workaround for SelectWholeModel bug if (GetSelectedComponentCount() == 0) SetState(kEmpty); fLowBound = 0; // Selections assume that the caller has taken care of locking the model. fHighBound = GetModelForReading()->GetNumTiles() - 1; if (GetState() == kEmpty && fHighBound != -1) SetState(kNotEmpty); } // This function is called when an empty selection is needed // The base class function DeselectAll() must be called. void TTilesSelection::DeselectAll() { TGUIEmbedderModelSelectionFor::DeselectAll(); // Now IsEmpty() will return true fLowBound = 0; fHighBound = 0; } // This function is called whenever the selection is undefined and cannot be // operated on by a command. // The base class function SetUndefined() must be called. void TTilesSelection::SetUndefined() { // The default for SetUndefined is DeselectAll TGUIEmbedderModelSelectionFor::SetUndefined(); // Now IsDefined() will return false fLowBound = 0; fHighBound = 0; } void TTilesSelection::SelectTile(TileIndex tileIndex) { // Selections assume that the caller has taken care of locking the model. TileIndex maxIndex = GetModelForReading()->GetNumTiles() - 1; // Check for illegal selection if (tileIndex >= 0 && tileIndex <= maxIndex) { fLowBound = tileIndex; fHighBound = tileIndex; SetState (kNotEmpty); // Now IsEmpty() will return false and IsDefined() will return true } else { // illegal selection DeselectAll(); } } bool TTilesSelection::ContainsTile (TileIndex whichTile) const { return (!IsEmpty() && whichTile >= fLowBound && whichTile <= fHighBound); } // Copy the source model data specified by this selection into the destination model // specified in the passed parameter. Called by the Presentation Framework to copy the // selection to the clipboard when the user chooses Copy. void TTilesSelection::CopyDataIntoModelSubclass( TTilesModel& destModel ) const { TileIndex i; if (!IsEmpty()) { // Selections assume that the caller has taken care of locking the model. const TTilesModel* sourceModel = GetModelForReading(); for (i = fLowBound; i <= fHighBound; i++) { // copy each TTile in the source model and copy to theDestModel destModel.AdoptTile(new TTile(*(sourceModel->GetTileForReading(i)))); } } } // Move (copy and delete) the source model data specified by this selection into the // destination model specified in the passed parameter. The destination model is assumed // to be empty. Called by the Presentation Framework to copy the selection to the clipboard // when the user chooses Cut or before a paste over the selection occurs to support undo // after a paste. This function should set this selection to the new insertion point after // the move and should be the inverse of MoveDataIntoModelSubclass so that undo/redo will work. void TTilesSelection::MoveDataIntoModelSubclass(TTilesModel& destModel ) { TileIndex i; if (!IsEmpty()) { // Selections assume that the caller has taken care of locking the model. TTilesModel* sourceModel = GetModelForWriting(); // Copy each TTile selected by this selection in the source model to the destination model. for (i = fLowBound; i <= fHighBound; i++) { destModel.AdoptTile(new TTile(*(sourceModel->GetTileForReading(i)))); } // Now delete each tile selected by this selection in the source model for (i = fLowBound; i <= fHighBound; i++) { // The fLowBound instead of i in the call to OrphanTile looks // strange, but the array will compress each time a TTile is // removed, so the next TTile moves into the fLowBound position. TTile* tile = sourceModel->OrphanTile(fLowBound); delete tile; } // Now update this selection. Since all the selected elements were deleted, the // selection is empty. In other selections, text for example, this selection would be set // to the new insertion point. DeselectAll(); } } // Copy the data from the source model specified by the parameter over the data in the // destination model selected by this selection. The data in the source model should completely // replace whatever data is specified by this selection at the start. Called by the Presentation // during a paste operation. After the move, this function should set this selection to the // new data moved in (the selection range may increase or decrease after the move) and should // be the inverse of MoveDataIntoModelSubclass so that undo/redo will work. void TTilesSelection::MoveDataOutofModelSubclass(TTilesModel& sourceModel ) { TileIndex i; // Selections assume that the caller has taken care of locking the model. TTilesModel* destModel = GetModelForWriting(); // If there are tiles to copy from source model TileIndex numTilesToCopy = sourceModel.GetNumTiles(); if (numTilesToCopy > 0) { // First delete each tile currently selected by this selection in the destination model if (!IsEmpty()) { for (i = fLowBound; i <= fHighBound; i++) { // The fLowBound instead of i in the call to OrphanTile looks // strange, but the array will compress each time a TTile is // removed, so the next TTile moves into the fLowBound position. TTile* tile = destModel->OrphanTile(fLowBound); delete tile; } // Now update this selection. Since all the selected elements were deleted, the // selection is empty. In other selections, text for example, this selection would be set // to the new insertion point. DeselectAll(); } // Copy the first tile and store the index as the low bound fLowBound = fHighBound = destModel->AdoptTile(new TTile(*(sourceModel.GetTileForReading(0)))); // Copy the rest and store the last index as the high bound for (i = 1; i < numTilesToCopy; i++) { fHighBound = destModel->AdoptTile(new TTile(*(sourceModel.GetTileForReading(i)))); } // Set the state to not empty to indicate a selection has been made. SetState(kNotEmpty); } }