// $Revision: 1.29 $ // PickerModel.C // Copyright (C) 1994, 1995 Taligent, Inc. All rights reserved. #ifndef TaligentSamples_PICKERMODEL #include "PickerModel.h" #endif #ifndef TaligentSamples_ATOMICMODEL #include #endif //============================================================================== // TPickerModel ModelDefinitionsMacroOne(TPickerModel, kOriginalVersion, TModel); TPickerModel::TPickerModel() : TModel(), fStocks(new TOperatorKeyValuePairComparator, NIL), fStockTimeStamp() { } TPickerModel::TPickerModel(const TPickerModel& source) : TModel(source), fStocks(new TOperatorKeyValuePairComparator, NIL), fStockTimeStamp(source.fStockTimeStamp) { CopyContentsFrom(source); } TPickerModel::~TPickerModel() { fStocks.DeleteAll(); } TPickerModel& TPickerModel::operator=(const TPickerModel& source) { if (&source != this) { TModel::operator=(source); fStocks.DeleteAll(); CopyContentsFrom(source); fStockTimeStamp = source.fStockTimeStamp; } return *this; } TStream& TPickerModel::operator>>=(TStream& toStream) const { ::WriteVersion(toStream, kOriginalVersion); TModel::operator>>=(toStream); // There's a bug in the streamer I would normally use, so I'm streaming // each item in the dictionary by hand. This is a common technique when // performance is an issue. fStocks.Count() >>= toStream; TDictionaryOfIterator iterator(&fStocks); for (TKeyValuePair* pair = iterator.First(); pair != NIL; pair = iterator.Next()) { *pair->GetKey() >>= toStream; ::Flatten(pair->GetValue(), toStream); } fStockTimeStamp >>= toStream; return toStream; } TStream& TPickerModel::operator<<=(TStream& fromStream) { ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion); TModel::operator<<=(fromStream); fStocks.DeleteAll(); CollectionCount count; count <<= fromStream; while (count--) { TStandardText* key = new TStandardText; *key <<= fromStream; TStockData* value; ::Resurrect(value, fromStream); fStocks.AddKeyValuePair(key, value); } fStockTimeStamp <<= fromStream; return fromStream; } bool TPickerModel::operator==(const TPickerModel& other) const { return other.fStocks == fStocks; } long TPickerModel::Hash() const { return fStocks.Hash(); } TModelSelection* TPickerModel::CreateSelection() const { return new TPickerSelection(*this); } void TPickerModel::AdoptStocks(TCollectionOf& stocks) { TDeleterFor > iter = stocks.CreateIterator(); for (TStockData* adoptee = iter->First(); adoptee != NIL; adoptee = iter->Next()) { AdoptStock(adoptee); } } void TPickerModel::AdoptStock(TStockData* adoptee) { ::Assertion(adoptee != NIL, "Can't adopt NIL stock"); // Remove stock with the same name if it exists, and adopt the new // one in its place. const TStandardText& name = adoptee->GetName(); TStandardText* theActualKey = fStocks.MemberByKey(name); if (theActualKey != NIL) { delete fStocks.Delete(theActualKey); } fStocks.AddKeyValuePair(::Copy(name), adoptee); } TStockData* TPickerModel::OrphanStock(const TStandardText& name) { return fStocks.RemoveByKey(name); } const TStockData* TPickerModel::GetStock(const TStandardText& name) const { return fStocks.ValueAt(name); } void TPickerModel::GetNames(TCollectionOf& fill) const { TDictionaryOfIterator iter(&fStocks); for (TKeyValuePair* pair = iter.First(); pair != NIL; pair = iter.Next()) { fill.Add(pair->GetKey()); } } void TPickerModel::CopyNames(TCollectionOf& fill) const { TDictionaryOfIterator iter(&fStocks); for (TKeyValuePair* pair = iter.First(); pair != NIL; pair = iter.Next()) { fill.Add(::Copy(*pair->GetKey())); } } TPseudoTimeStamp TPickerModel::GetStockTimeStamp() const { return fStockTimeStamp; } void TPickerModel::SetStockTimeStamp(const TPseudoTimeStamp& newTimeStamp) { fStockTimeStamp = newTimeStamp; } void TPickerModel::CopyContentsFrom(const TPickerModel& source) { TDictionaryOfIterator iter(&source.fStocks); for (TKeyValuePair* pair = iter.First(); pair != NIL; pair = iter.Next()) { // Calling ::Copy on a TKeyValuePair will result in an identical // copy of the TKeyValuePair, pointing to the original key and value. // What we want is a new TKeyValuePair, pointing to copies of the // original key and value. fStocks.AddKeyValuePair(::Copy(*pair->GetKey()), ::Copy(*pair->GetValue())); } } //============================================================================== // TPickerSelection TaligentTypeExtensionMacro(TPickerSelection); TPickerSelection::TPickerSelection() : TModelSelection(), MDataExchanger(this), fStocks( new TOperatorComparator, new TMonomorphicStreamer) { } TPickerSelection::TPickerSelection(const TPickerSelection& source) : TModelSelection(source), MDataExchanger(this), fStocks( new TOperatorComparator, new TMonomorphicStreamer) { CopyContentsFrom(source); } TPickerSelection::TPickerSelection(const TModelReference& ref) : TModelSelection(ref), MDataExchanger(this), fStocks( new TOperatorComparator, new TMonomorphicStreamer) { } TPickerSelection::~TPickerSelection() { fStocks.DeleteAll(); } TPickerSelection& TPickerSelection::operator=(const TPickerSelection& source) { if(&source != this) { TModelSelection::operator=(source); MDataExchanger::operator=(source); CopyContentsFrom(source); } return *this; } TStream& TPickerSelection::operator>>=(TStream& toStream) const { ::WriteVersion(toStream, kOriginalVersion); TModelSelection::operator>>=(toStream); fStocks >>= toStream; return toStream; } TStream& TPickerSelection::operator<<=(TStream& fromStream) { ::ReadVersion(fromStream, kOriginalVersion, kOriginalVersion); TModelSelection::operator<<=(fromStream); fStocks.DeleteAll(); fStocks <<= fromStream; return fromStream; } void TPickerSelection::CopyContentsFrom(const TPickerSelection& source) { fStocks.DeleteAll(); TDeleterFor > iterator = source.fStocks.CreateIterator(); for (TStandardText* name = iterator->First(); name != NIL; name = iterator->Next()) { fStocks.Add(::Copy(*name)); } } void TPickerSelection::CreateAvailableTypesList(TSequenceOf& theTypes) const { // The first type in the list must be the native type, TPickerModel. MDataExchanger::CreateAvailableTypesList(theTypes); if (fStocks.Count() == 1) { theTypes.Add(new TTypeDescription(StaticTypeInfo(TAtomicModelOn))); } } void TPickerSelection::ChooseTypes(const TSequenceOf& theChoices, TSequenceOf& theChosenTypes) const { TTypeDescription* choice = theChoices.Member(TTypeDescription(StaticTypeInfo(TAtomicModelOn))); if (choice != NIL) { theChosenTypes.Add(choice); } MDataExchanger::ChooseTypes(theChoices, theChosenTypes); } void TPickerSelection::DeselectAll() { TModelSelection::DeselectAll(); fStocks.DeleteAll(); } void TPickerSelection::SelectWholeModel() { TModelSelection::SelectWholeModel(); const TPickerModel* model = (const TPickerModel*)GetModelForReading(); fStocks.DeleteAll(); model->CopyNames(fStocks); SetState(fStocks.IsEmpty() ? kEmpty : kNotEmpty); } void TPickerSelection::SelectStock(const TStandardText& name) { const TPickerModel* model = (const TPickerModel*)GetModelForReading(); if (model->GetStock(name) != NIL) { fStocks.Add(::Copy(name)); SetState(kNotEmpty); } } void TPickerSelection::DeselectStock(const TStandardText& name) { fStocks.Remove(name); if (fStocks.Count() == 0) { SetState(kEmpty); } else { SetState(kNotEmpty); } } void TPickerSelection::GetSelectedStocks(TCollectionOf& fill) const { const TPickerModel* model = (const TPickerModel*)GetModelForReading(); TArrayOfIterator iterator(&fStocks); for (TStandardText* name = iterator.First(); name != NIL; name = iterator.Next()) { fill.Add((TStockData*)model->GetStock(*name)); // Cast away const. } } void TPickerSelection::GetSelectedNames(TCollectionOf& fill) const { const TPickerModel* model = (const TPickerModel*)GetModelForReading(); TArrayOfIterator iterator(&fStocks); for (TStandardText* name = iterator.First(); name != NIL; name = iterator.Next()) { fill.Add(name); } } void TPickerSelection::ExtendTo(const TPickerSelection& other) { TArrayOfIterator otherIter(&other.fStocks); TStandardText* stockName = otherIter.First(); while (stockName != NIL) { SelectStock(*stockName); stockName = otherIter.Next(); } } TModel* TPickerSelection::HandleCopyData(const TTypeDescription& theType) const { TModel* result = NIL; if (theType == TTypeDescription(StaticTypeInfo(TAtomicModelOn))) { ::Assertion(fStocks.Count() == 1, "Can't export TAtomicModelOn unless only 1 stock is selected."); const TPickerModel* model = (const TPickerModel*)GetModelForReading(); const TStockData* stock = model->GetStock(*fStocks.First()); result = new TAtomicModelOn(::Copy(*stock)); } else { TPickerModel* emptyModel = CreateEmptyModel(); HandleCopyDataInto(*emptyModel); result = emptyModel; } return result; } void TPickerSelection::HandleCopyDataInto(TModel& theModel) const { TPickerModel* destModel = NIL; ::DynamicCastTo(destModel, &theModel); if (destModel != NIL) { const TPickerModel* selectedModel = (const TPickerModel*)GetModelForReading(); TArrayOfIterator iterator(&fStocks); for (TStandardText* name = iterator.First(); name != NIL; name = iterator.Next()) { destModel->AdoptStock(::Copy(*selectedModel->GetStock(*name))); } } else { // This function should not be called to copy into a TAtomicModelOn. TAtomicModelOn* modelOn; DynamicCastTo(modelOn, &theModel); ::Assertion(modelOn == NIL, "HandleCopyDataInto cannot be called for TAtomicModelOn"); } } TModel* TPickerSelection::HandleOrphanData() { // This function returns a new model of the same type as the current model. TPickerModel* orphanedData = CreateEmptyModel(); if (IsDefined() && !IsEmpty()) { TPickerModel* selectedModel = (TPickerModel*)GetModelForWriting(); TArrayOfIterator iterator(&fStocks); for (TStandardText* name = iterator.First(); name != NIL; name = iterator.Next()) { orphanedData->AdoptStock(selectedModel->OrphanStock(*name)); } fStocks.DeleteAll(); } SetState(kEmpty); return orphanedData; } TModel* TPickerSelection::HandleReplaceData(TModel* adoptedNewData) { TDeleterFor dataDeleter(adoptedNewData); TDeleterFor undoData = HandleOrphanData(); TPickerModel* selectedModel = (TPickerModel*)GetModelForWriting(); if (IsDefined()) { TAtomicModelOn* modelOn = NIL; ::DynamicCastTo(modelOn, adoptedNewData); if (modelOn != NIL) { TStockData* stock = modelOn->CopyValue(); selectedModel->AdoptStock(stock); fStocks.Add(::Copy(stock->GetName())); SetState(kNotEmpty); } else { TPickerModel* newModel = NIL; DynamicCastTo(newModel, adoptedNewData); if (newModel != NIL) { TArrayOf names( new TOperatorComparator, new TPolymorphicStreamer); newModel->CopyNames(names); TArrayOfIterator iterator(&names); for (TStandardText* name = iterator.First(); name != NIL; name = iterator.Next()) { TStockData* stock = newModel->OrphanStock(*name); selectedModel->AdoptStock(stock); fStocks.Add(::Copy(*name)); } SetState(kNotEmpty); } } } return undoData.OrphanObject(); } TPickerModel* TPickerSelection::CreateEmptyModel() const { return new TPickerModel; }