// $Revision: 1.20 $ // Copyright (C) 1993-1995 Taligent, Inc. All rights reserved. # ifndef Taligent_COLLECTIONS # include # endif # ifndef Taligent_NOTIFICATION # include # endif # ifndef Taligent_BASICDOCUMENTSTORAGE # include # endif # ifndef Taligent_BASICDOCUMENT # include # endif # ifndef Taligent_BASICPLACES # include # endif # ifndef Taligent_COMPOUNDDOCUMENTSTORAGE # include # endif # ifndef Taligent_COMPOUNDDOCUMENT # include # endif # ifndef Taligent_COMPOUNDDOCUMENTCOMMAND # include # endif # ifndef Taligent_GUICOMPOUNDDOCUMENT # include "GUICompoundDocument.h" # endif # ifndef Taligent_GUICOMPOUNDDOCUMENTEMBEDDER # include "GUICompoundDocumentEmbedder.h" # endif # ifndef Taligent_GUICOMPOUNDDOCUMENTPRIVATE # include "GUICompoundDocumentPrivate.h" # endif // // TGUIEmbedderModel Implementation // ModelDefinitionsMacroOne( TGUIEmbedderModel, kOriginalVersion, TModel ); static TToken kAddedComponent("TGUIEmbedderModel::kAddedComponent"); static TToken kRemovedComponent("TGUIEmbedderModel::kRemovedComponent"); static TToken kComponentLayoutChanged("TGUIEmbedderModel::kComponentLayoutChanged"); TGUIEmbedderModel::TGUIEmbedderModel() : TModel(), fComponents( new (kSameHeap, this) TOperatorComparator, new (kSameHeap, this) TMonomorphicStreamer ) { } TGUIEmbedderModel::TGUIEmbedderModel(const TGUIEmbedderModel& copy) : TModel( copy ), fComponents( new (kSameHeap, this) TOperatorComparator, new (kSameHeap, this) TMonomorphicStreamer ) { TDequeOfIterator i( ©.fComponents ); for ( TComponentArea* aLayout = i.First(); aLayout != NIL; aLayout = i.Next() ) { Adopt( new (kSameHeap, this) TComponentArea( *aLayout ) ); } } TGUIEmbedderModel::~TGUIEmbedderModel() { fComponents.DeleteAll(); } TModelSelection* TGUIEmbedderModel::CreateSelection() const { return new TGUIEmbedderModelSelection( *this ); } void TGUIEmbedderModel::DeleteAll() { // Remove existing components from the hierarchy and delete them. TDequeOfIterator i( &fComponents ); for ( TComponentArea* aLayout = i.First(); aLayout != NIL; aLayout = i.Next() ) { RemoveComponent( *aLayout->GetComponent() ); aLayout->GetComponent()->DeleteStore(); } fComponents.DeleteAll(); } void TGUIEmbedderModel::Adopt(TComponentArea* theLayout) { fComponents.Add( theLayout ); AddComponent( theLayout->GetComponent() ); TDocumentComponentNotification theNotification( GetAddedComponentInterest(), *theLayout->GetComponent() ); NotifyOfChange( theNotification ); } TComponentArea* TGUIEmbedderModel::Orphan(TComponentArea& theLayout) { TComponentArea* orphanedLayout = fComponents.Remove( theLayout ); if ( orphanedLayout != NIL ) { RemoveComponent( *orphanedLayout->GetComponent() ); TDocumentComponentNotification theNotification( GetRemovedComponentInterest(), *orphanedLayout->GetComponent() ); NotifyOfChange( theNotification ); } return orphanedLayout; } TComponentArea* TGUIEmbedderModel::LookupComponent( const TDocumentComponentReference& aReference ) { TComponentArea* foundLayout = NIL; TDequeOfIterator i( &fComponents ); for ( TComponentArea* aLayout = i.First(); aLayout != NIL && foundLayout == NIL; aLayout = i.Next() ) { if ( aReference.IsReferenceFor( *aLayout->GetComponent() ) ) { foundLayout = aLayout; } } return foundLayout; } const TComponentArea* TGUIEmbedderModel::LookupComponent( const TDocumentComponentReference& aReference ) const { const TComponentArea* foundLayout = NIL; TDequeOfIterator i( &fComponents ); for ( TComponentArea* aLayout = i.First(); aLayout != NIL && foundLayout == NIL; aLayout = i.Next() ) { if ( aReference.IsReferenceFor( *aLayout->GetComponent() ) ) { foundLayout = aLayout; } } return foundLayout; } TIteratorOver* TGUIEmbedderModel::CreateComponentIterator() const { return new TDequeOfIterator ( &fComponents ); } void TGUIEmbedderModel::SetComponentArea( const TDocumentComponentReference& theComponent, const TGArea& theArea ) { TComponentArea* theLayout = LookupComponent( theComponent ); if ( theLayout != NIL ) { theLayout->SetArea( theArea ); TDocumentComponentNotification theNotification( GetComponentAreaChangedInterest(), *theLayout->GetComponent() ); NotifyOfChange( theNotification ); } } TModelInterest TGUIEmbedderModel::GetAddedComponentInterest() const { return TModelInterest( *this, kAddedComponent ); } TModelInterest TGUIEmbedderModel::GetRemovedComponentInterest() const { return TModelInterest( *this, kRemovedComponent ); } TModelInterest TGUIEmbedderModel::GetComponentAreaChangedInterest() const { return TModelInterest( *this, kComponentLayoutChanged ); } TGUIEmbedderModel& TGUIEmbedderModel::operator=(const TGUIEmbedderModel& copy) { if ( this != © ) { TModel::operator=( copy ); // Remove existing components from the hierarchy and delete them. TDequeOfIterator i( &fComponents ); for ( TComponentArea* aLayout = i.First(); aLayout != NIL; aLayout = i.Next() ) { RemoveComponent( *aLayout->GetComponent() ); aLayout->GetComponent()->DeleteStore(); } fComponents.DeleteAll(); TDequeOfIterator i1( ©.fComponents ); for ( aLayout = i1.First(); aLayout != NIL; aLayout = i1.Next() ) { Adopt( new (kSameHeap, this) TComponentArea( *aLayout ) ); } } return *this; } TStream& TGUIEmbedderModel::operator>>= (TStream& toWhere) const { WriteVersion(toWhere); TModel::operator>>=(toWhere); fComponents >>= toWhere; return toWhere; } TStream& TGUIEmbedderModel::operator<<= (TStream& fromWhere) { VersionInfo version = ReadVersion(fromWhere); switch (version) { case kOriginalVersion: { TModel::operator<<=(fromWhere); // Remove existing components from the hierarchy and delete them. TDequeOfIterator i( &fComponents ); for ( TComponentArea* aLayout = i.First(); aLayout != NIL; aLayout = i.Next() ) { RemoveComponent( *aLayout->GetComponent() ); aLayout->GetComponent()->DeleteStore(); } fComponents.DeleteAll(); fComponents <<= fromWhere; // If we are not streaming for filing, we need to add these // components into the hierarchy. if ( !TStorageMechanism::IsStreamForFiling( &fromWhere ) ) { TDequeOfIterator i1( &fComponents ); for ( aLayout = i1.First(); aLayout != NIL; aLayout = i1.Next() ) { AddComponent( aLayout->GetComponent() ); } } } break; default: throw TInvalidVersionError(); break; } return fromWhere; } // // TComponentArea Implementation // VersionDefinitionsMacro(TComponentArea, kOriginalVersion); TComponentArea::TComponentArea() : fComponent( NIL ) { } TComponentArea::TComponentArea( TDocumentComponent* componentToAdopt ) : fComponent( componentToAdopt ), fArea ( TGRect( 0, 0, 20, 20 ) ) { } TComponentArea::TComponentArea( TDocumentComponent* componentToAdopt, const TGArea& theArea ) : fComponent( componentToAdopt ), fArea( theArea ) { } TComponentArea::TComponentArea( const TComponentArea& copy) : fComponent( ::CopyPointer( copy.fComponent ) ), fArea( copy.fArea ) { } TComponentArea::~TComponentArea() { delete fComponent; } TGArea TComponentArea::GetArea() const { return fArea; } void TComponentArea::SetArea( const TGArea& theArea ) { fArea = theArea; } TDocumentComponent* TComponentArea::OrphanComponent() { TDocumentComponent* theComponent = fComponent; fComponent = NIL; return theComponent; } TDocumentComponent* TComponentArea::GetComponent() { if (fComponent == NIL) { throw TCompoundDocumentException( TCompoundDocumentException:: kNILComponent ); } return fComponent; } const TDocumentComponent* TComponentArea::GetComponent() const { if (fComponent == NIL) { throw TCompoundDocumentException( TCompoundDocumentException:: kNILComponent ); } return fComponent; } HashResult TComponentArea::Hash() const { return fComponent->Hash(); } bool TComponentArea::operator==( const TComponentArea& right ) const { return fArea == right.fArea && fComponent == right.fComponent; } bool TComponentArea::operator!=( const TComponentArea& right ) const { return !operator==( right ); } TStream& TComponentArea::operator>>= ( TStream& toWhere) const { unsigned char temp = 0xff; temp >>= toWhere; ::WriteVersion(toWhere, kOriginalVersion); ::Flatten( fComponent, toWhere ); fArea >>= toWhere; return toWhere; } TStream& TComponentArea::operator<<= ( TStream& fromWhere) { unsigned char temp; temp <<= fromWhere; VersionInfo version; if ( temp == 0xff ) version = ::ReadVersion(fromWhere, kOriginalVersion, kOriginalVersion); else version = temp; switch (version) { case kOriginalVersion: ::Resurrect( fComponent, fromWhere ); fArea <<= fromWhere; break; default: throw TInvalidVersionError(); break; } return fromWhere; } TComponentArea& TComponentArea::operator=( const TComponentArea& other) { if ( &other != this) { // TComponentArea specific assignment here fArea = other.fArea; delete fComponent; fComponent = ::CopyPointer( other.fComponent, ::kSameHeap, (void*) this); } return *this; } // // MEmbeddedComponentAccessor Implementation // // VersionDefinitionsMacro(MEmbeddedComponentAccessor,kOriginalVersion); DynamicCastDefinitionsMacroZero(MEmbeddedComponentAccessor); MEmbeddedComponentAccessor::MEmbeddedComponentAccessor() { } MEmbeddedComponentAccessor::MEmbeddedComponentAccessor( const MEmbeddedComponentAccessor&) { } MEmbeddedComponentAccessor::~MEmbeddedComponentAccessor() { } void MEmbeddedComponentAccessor::AddInterests(TSetOf &set) { } MEmbeddedComponentAccessor& MEmbeddedComponentAccessor::operator=(const MEmbeddedComponentAccessor& other) { if ( &other != this) { // MEmbeddedComponentAccessor specific assignment here } return *this; } TStream& MEmbeddedComponentAccessor::operator>>=(TStream& toWhere ) const { ::WriteVersion(toWhere, kOriginalVersion); return toWhere; } TStream& MEmbeddedComponentAccessor::operator<<=(TStream& fromWhere) { ::ReadVersion(fromWhere, kOriginalVersion, kOriginalVersion); return fromWhere; } // // TGUIEmbedderModelSelection Implementation // TaligentTypeExtensionMacro(TGUIEmbedderModelSelection) TGUIEmbedderModelSelection::TGUIEmbedderModelSelection() : TModelSelection(), MDataExchanger( this ), fComponents( new (kSameHeap, this) TOperatorComparator, new (kSameHeap, this) TMonomorphicStreamer ) { } TGUIEmbedderModelSelection::TGUIEmbedderModelSelection( const TModelReference& theModelRef ) : TModelSelection( theModelRef ), MDataExchanger( this ), fComponents( new (kSameHeap, this) TOperatorComparator, new (kSameHeap, this) TMonomorphicStreamer ) { } TGUIEmbedderModelSelection::TGUIEmbedderModelSelection( const TGUIEmbedderModel& theModel) : TModelSelection( theModel.GetReference() ), MDataExchanger( this ), fComponents( new (kSameHeap, this) TOperatorComparator, new (kSameHeap, this) TMonomorphicStreamer ) { } TGUIEmbedderModelSelection::TGUIEmbedderModelSelection( const TGUIEmbedderModelSelection& copy) : TModelSelection( copy ), MDataExchanger( this ), fComponents( new (kSameHeap, this) TOperatorComparator, new (kSameHeap, this) TMonomorphicStreamer ) { TSetOfIterator i( ©.fComponents ); for ( TDocumentComponentReference* aRef = i.First(); aRef != NIL; aRef = i.Next() ) { fComponents.Add( ::Copy( *aRef ) ); } } TGUIEmbedderModelSelection& TGUIEmbedderModelSelection::operator=(const TGUIEmbedderModelSelection& copy) { if ( this != © ) { TModelSelection::operator=( copy ); fComponents.DeleteAll(); TSetOfIterator i( ©.fComponents ); for ( TDocumentComponentReference* aRef = i.First(); aRef != NIL; aRef = i.Next() ) { fComponents.Add( ::Copy( *aRef ) ); } } return *this; } TGUIEmbedderModelSelection::~TGUIEmbedderModelSelection() { fComponents.DeleteAll(); } void TGUIEmbedderModelSelection::AddInterests(TSetOf &set) { const TGUIEmbedderModel* theModel = GetModelForReading(); set.Add( new TModelInterest( theModel->GetComponentAreaChangedInterest() )); } bool TGUIEmbedderModelSelection::IsEmpty() const { return TModelSelection::IsEmpty() && fComponents.IsEmpty(); } void TGUIEmbedderModelSelection::DeselectAll() { TModelSelection::DeselectAll(); fComponents.DeleteAll(); } void TGUIEmbedderModelSelection::SelectWholeModel() { TModelSelection::SelectWholeModel(); const TGUIEmbedderModel* theModel = TGUIEmbedderModel::LookupForReading( GetModelReference() ); fComponents.DeleteAll(); TDeleterFor > i = theModel->CreateComponentIterator(); for ( TComponentArea* theLayout = i->First(); theLayout != NIL; theLayout = i->Next() ) { fComponents.Add( new (kSameHeap, this) TDocumentComponentReference( *theLayout->GetComponent() ) ); } if (fComponents.IsEmpty()) SetState(TModelSelection::kEmpty); } void TGUIEmbedderModelSelection::CreateAvailableTypesList( TSequenceOf& theTypes) const { // We don't offer as ourself if the selected component count is == 0, because then // we can never embed our native type into another model derived from TGUIEmbedderModelSelection. if ( GetSelectedComponentCount() > 0 ) { theTypes.Add( new (kSameHeap, &theTypes) TTypeDescription( TGUIEmbedderModel::GetTypeDescription() ) ); } } void TGUIEmbedderModelSelection::ChooseTypes( const TSequenceOf& theChoices, TSequenceOf& theChosen ) const { TTypeDescription* member = theChoices.Member( TGUIEmbedderModel::GetTypeDescription() ); if ( member ) { theChosen.Add( member ); } member = theChoices.Member( TEmbedderModel::GetTypeDescription() ); if ( member ) { theChosen.Add( member ); } } void TGUIEmbedderModelSelection::GetComponentArea( const TDocumentComponentReference& theCompRef, TGArea& theArea ) const { const TGUIEmbedderModel* theModel = GetModelForReading(); const TComponentArea* theLayout = theModel->LookupComponent( theCompRef ); if ( theLayout == NIL ) { throw TCompoundDocumentException( TCompoundDocumentException:: kDocumentComponentDoesNotExist ); } theArea = theLayout->GetArea(); } void TGUIEmbedderModelSelection::SetComponentArea( const TDocumentComponentReference& theCompRef, const TGArea& theArea ) { TGUIEmbedderModel* theModel = GetModelForWriting(); theModel->SetComponentArea( theCompRef, theArea ); } void TGUIEmbedderModelSelection::SelectComponent( const TDocumentComponentReference& theComponent) { SetState( kNotEmpty ); if ( !fComponents.Member( theComponent ) ) { fComponents.Add( ::Copy( theComponent ) ); } } void TGUIEmbedderModelSelection::DeselectComponent( const TDocumentComponentReference& theComponent ) { delete fComponents.Remove( theComponent ); } void TGUIEmbedderModelSelection::DeselectAllComponents() { fComponents.DeleteAll(); } long TGUIEmbedderModelSelection::GetSelectedComponentCount() const { return fComponents.Count(); } TIteratorOver* TGUIEmbedderModelSelection::CreateSelectedComponentIterator() const { return fComponents.CreateIterator(); } bool TGUIEmbedderModelSelection::IsSelected( const TDocumentComponentReference& theComponent ) const { return fComponents.Member( theComponent ) != NIL; } void TGUIEmbedderModelSelection::GetSelectedComponents( TCollectionOf& theComponents ) const { TSetOfIterator i( &fComponents ); for ( TDocumentComponentReference* aRef = i.First(); aRef != NIL; aRef = i.Next() ) { theComponents.Add( ::Copy( *aRef ) ); } } const TGUIEmbedderModel* TGUIEmbedderModelSelection::GetModelForReading() const { const TModel* theModel = TModelSelection::GetModelForReading(); TGUIEmbedderModel* theModelSubclass; DynamicCastTo( theModelSubclass, theModel ); if (theModelSubclass == NIL ) { throw TCompoundDocumentException( TCompoundDocumentException:: kModelDoesNotExist ); } return theModelSubclass; } TGUIEmbedderModel* TGUIEmbedderModelSelection::GetModelForWriting() const { TModel* theModel = TModelSelection::GetModelForWriting(); TGUIEmbedderModel* theModelSubclass; DynamicCastTo( theModelSubclass, theModel ); if (theModelSubclass == NIL ) { throw TCompoundDocumentException( TCompoundDocumentException:: kModelDoesNotExist ); } return theModelSubclass; } bool TGUIEmbedderModelSelection::IsEqual( const MCollectible* other) const { bool isEqual = TModelSelection::IsEqual( other ); if ( isEqual ) { const TGUIEmbedderModelSelection* otherSelection = (TGUIEmbedderModelSelection*)other; isEqual = fComponents.IsEqual( &otherSelection->fComponents ); } return isEqual; } TStream& TGUIEmbedderModelSelection::operator>>=( TStream& toWhere) const { ::WriteVersion(toWhere); TModelSelection::operator>>=(toWhere); fComponents >>= toWhere; return toWhere; } TStream& TGUIEmbedderModelSelection::operator<<=( TStream& fromWhere) { VersionInfo version = ReadVersion(fromWhere); switch (version) { case kOriginalVersion: TModelSelection::operator<<=(fromWhere); fComponents.DeleteAll(); fComponents <<= fromWhere; break; default: throw TInvalidVersionError(); break; } return fromWhere; } TModel* TGUIEmbedderModelSelection::HandleCopyData(const TTypeDescription& theType) const { TModel* theModel = NIL; if ( theType == TEmbedderModel::GetTypeDescription() ) { theModel = new TEmbedderModel; } else if ( theType == TGUIEmbedderModel::GetTypeDescription() ) { theModel = new TGUIEmbedderModel; } else { theModel = HandleCreateModel( theType ); } if ( theModel != NIL ) { HandleCopyDataInto( *theModel ); } else { throw TCompoundDocumentException( TCompoundDocumentException:: kTypeUnacceptable ); } return theModel; } TModel* TGUIEmbedderModelSelection::HandleCreateModel( const TTypeDescription& theType) const { return NIL; } void TGUIEmbedderModelSelection::HandleCopyDataInto(TModel& theModel) const { TEmbedderModel* theEmbedderModel = NIL; DynamicCastTo( theEmbedderModel, &theModel ); if ( theEmbedderModel != NIL ) { CopyDataIntoEmbedderModel( *theEmbedderModel ); } else { TGUIEmbedderModel* theGUIEmbedderModel = NIL; DynamicCastTo( theGUIEmbedderModel, &theModel ); if ( theGUIEmbedderModel != NIL ) { CopyDataIntoGUIEmbedderModel( *theGUIEmbedderModel ); } else { throw TCompoundDocumentException( TCompoundDocumentException:: kTypeUnacceptable ); } } } TModel* TGUIEmbedderModelSelection::HandleReplaceData(TModel* newModel) { TModel* undoModel = HandleOrphanData(); TEmbedderModel* theEmbedderModel; DynamicCastTo( theEmbedderModel, newModel ); if ( theEmbedderModel != NIL ) { MoveDataOutofEmbedderModel( *theEmbedderModel ); } else { TGUIEmbedderModel* theGUIEmbedderModel = NIL; DynamicCastTo( theGUIEmbedderModel, newModel ); if ( theGUIEmbedderModel != NIL ) { MoveDataOutofGUIEmbedderModel( *theGUIEmbedderModel ); } } return undoModel; } TModel* TGUIEmbedderModelSelection::HandleOrphanData() { TGUIEmbedderModel* undoModel = new TGUIEmbedderModel; MoveDataIntoGUIEmbedderModel( *undoModel ); return undoModel; }; void TGUIEmbedderModelSelection::MoveDataIntoGUIEmbedderModel( TGUIEmbedderModel& theDestModel ) { TGUIEmbedderModel* theModel = TGUIEmbedderModel::LookupForWriting( GetModelReference() ); TSetOfIterator i( &fComponents ); for ( TDocumentComponentReference* aComponent = i.First(); aComponent != NIL; aComponent = i.Next() ) { TComponentArea* theLayout = theModel->LookupComponent( *aComponent ); if ( theLayout != NIL ) { theModel->Orphan( *theLayout ); theDestModel.Adopt( theLayout ); } } fComponents.DeleteAll(); } void TGUIEmbedderModelSelection::CopyDataIntoEmbedderModel( TEmbedderModel& theModel ) const { const TGUIEmbedderModel* myModel = TGUIEmbedderModel::LookupForReading( GetModelReference() ); TSetOfIterator i( &fComponents ); for ( TDocumentComponentReference* aComponent = i.First(); aComponent != NIL; aComponent = i.Next() ) { const TComponentArea* theLayout = myModel->LookupComponent( *aComponent ); if ( theLayout != NIL ) { theModel.AdoptAndEmbed( ::CopyPointer( theLayout->GetComponent() ) ); } } } void TGUIEmbedderModelSelection::CopyDataIntoGUIEmbedderModel( TGUIEmbedderModel& theModel ) const { const TGUIEmbedderModel* myModel = TGUIEmbedderModel::LookupForReading( GetModelReference() ); TSetOfIterator i( &fComponents ); for ( TDocumentComponentReference* aComponent = i.First(); aComponent != NIL; aComponent = i.Next() ) { const TComponentArea* theLayout = myModel->LookupComponent( *aComponent ); if ( theLayout != NIL ) { theModel.Adopt( new (kSameHeap, this) TComponentArea( *theLayout ) ); } } } void TGUIEmbedderModelSelection::MoveDataOutofGUIEmbedderModel( TGUIEmbedderModel& newModel) { TGUIEmbedderModel* myModel = TGUIEmbedderModel::LookupForWriting( GetModelReference() ); TDeleterFor > i = newModel.CreateComponentIterator(); // Note that each iteration calls First rather than Next. This is // because the entries are being removed as we iterate, and the iterator // must be reset. for ( TComponentArea* theLayout = i->First(); theLayout != NIL; theLayout = i->First() ) { newModel.Orphan( *theLayout ); myModel->Adopt( theLayout ); SelectComponent( *theLayout->GetComponent() ); } } void TGUIEmbedderModelSelection::MoveDataOutofEmbedderModel(TEmbedderModel& newModel) { TGUIEmbedderModel* myModel = TGUIEmbedderModel::LookupForWriting( GetModelReference() ); TDeleterFor > i = newModel.CreateComponentIterator(); // Note that each iteration calls First rather than Next. This is // because the entries are being removed as we iterate, and the iterator // must be reset. TGPoint theOrigin( 10, 10 ); static TGPoint kIncrement( 8, 8 ); static TGPoint kSize( 80, 80 ); for ( TDocumentComponent* theComponent = i->First(); theComponent != NIL; theComponent = i->First() ) { newModel.OrphanAndUnembed( *theComponent ); // We do a staggered layout on the newly layed out components. myModel->Adopt( new (kSameHeap, this) TComponentArea( theComponent, TGRect( theOrigin, theOrigin + kSize ) ) ); SelectComponent( *theComponent ); theOrigin += kIncrement; } }