Перегрузка deepClone () Функция
Типовой код в этой секции - приближение к заданному по умолчанию поведению deepClone(). Глубокая клонируемая операция имеет две основных стадии:
§ Клонирование (Вы можете перегружать эту стадию)
§ Трансляция (Вы не будете должны повторно осуществить эту стадию; это может управляться тем, что помещено в карту ID)
В течение клонируемой стадии в этом примере, информация относительно старого объекта скопирована к новому объекту, используя определенный тип регистратора, чтобы выписать объект и читать это назад. Регистратор следит за объектами, принадлежащими первичному объекту так, чтобы они могли быть скопированы также.
Закончить клонируемую стадию
1 Создают новый объект того же самого типа как старый.
2 Добавляют новый объект его владельцу.
§ если объект - примитив, его владелец - запись таблицы блоков, и Вы можете использовать appendAcDbEntity().
§ если объект - AcDbObject, его владелец - AcDbDictionary, и Вы можете использовать setAt (), чтобы добавить это к словарю.
Если бы это - не первичный объект, Вы обычно добавили бы это к базе данных, используя addAcDbObject () и затем идентифицировать ее владельца, использующего setOwnerId ().
Чтобы устанавливать монопольное использование, владелец должен регистрировать из ID находящегося в собственности объекта, используя соответствующий тип монопольного использования.
3 Запрос dwgOut () на первоначальном объекте, используя глубокого клонируемого регистратора (AcDbDeepCloneFiler), чтобы выписать объект. (Или, если Вы перегружаете wblockClone () функция, использует AcDbWblockCloneFiler.)
4 Перематывают регистратора и затем вызывают dwgIn () на новом объекте.
5 Запроса setObjectIdsInFlux () на каждом новом объекте прежде, чем Вы добавляете его значение к карте объекта ID. Этот важный шаг используется, чтобы указать, что недавно созданный объект - часть глубокой клонируемой операции, и ее объект ID подчинен, чтобы измениться как часть стадии трансляции. Этот флажок автоматически выключен, когда трансляция полна.
6 Добавляют новую информацию к idMap. IdMap содержит AcDbIdPairs, которые являются парами старого (оригинала) и новых (клонированных) объектных ID. Конструктор для пары ID устанавливает первоначальный объект ID и флажок isPrimary. В этой точке, Вы устанавливаете объект ID для клонированного объекта, устанавливает флажок isCloned в TRUE, и добавляете (назначают) это на idMap.
7 Клонируют находящиеся в собственности объекты. (Этот шаг рекурсивен.)
§ Спрашивают регистратора, если имеются больше находящиеся в собственности объекты. (Для клона wblock, спросите, если имеются больше жесткие объекты.)
§ чтобы клонировать подобъект, получите его ID, и откройте объект для чтения.
§ Вызывают deepClone () на объекте. (Обратите внимание, что isPrimary установлен в FALSE, потому что это - находящийся в собственности объект.) deepClone () функция клонирует объект и устанавливает его владельца. Это также добавляет запись на карту ID.
§ Закрыли бы подобъект, если это было создано в это время.
§
Следующий типовой код иллюстрирует эти шаги:
Acad::ErrorStatus
AsdkPoly::deepClone(
AcDbObject* pOwner,
AcDbObject*& pClonedObject,
AcDbIdMapping& idMap,
Adesk::Boolean isPrimary) const
{
// You should always pass back pClonedObject == NULL
// if, for any reason, you do not actually clone it
// during this call. The caller should pass it in
// as NULL, but to be safe, we set it here as well.
//
pClonedObject = NULL;
// If this object is in the idMap and is already
// cloned, then return.
//
bool isPrim = false;
if (isPrimary)
isPrim = true;
AcDbIdPair idPair(objectId(), (AcDbObjectId)NULL, false, isPrim);
if (idMap.compute(idPair) && (idPair.value() != NULL))
return Acad::eOk;
// Step 1: Create the clone.
//
AsdkPoly *pClone = (AsdkPoly*)isA()->create();
if (pClone != NULL)
pClonedObject = pClone; // Set the return value.
else
return Acad::eOutOfMemory;
// Step 2: Append the clone to its new owner. In this
// example, the original object is derived from AcDbEntity,
// so the owner is expected to be an AcDbBlockTableRecord,
// unless an ownership relationship is set up with another
// object. In that case, it is important to establish a
// connection to that owner. This sample shows a generic
// method using setOwnerId().
//
AcDbBlockTableRecord *pBTR =
AcDbBlockTableRecord::cast(pOwner);
if (pBTR != NULL) {
pBTR->appendAcDbEntity(pClone);
} else {
if (isPrimary)
return Acad::eInvalidOwnerObject;
// Some form of this code is only necessary if
// anyone has set up an ownership for the object
// other than with an AcDbBlockTableRecord.
//
pOwner->database()->addAcDbObject(pClone);
pClone->setOwnerId(pOwner->objectId());
}
// Step 3: Now contents are copied to the clone. This is done
// using an AcDbDeepCloneFiler. This filer keeps a list of all
// AcDbHardOwnershipIds and AcDbSoftOwnershipIds contained in
// the object and its derived classes. This list is then used
// to know what additional, "owned" objects need to be cloned
// below.
//
AcDbDeepCloneFiler filer;
dwgOut(&filer);
// Step 4: Rewind the filer and read the data into the clone.
//
filer.seek(0L, AcDb::kSeekFromStart);
pClone->dwgIn(&filer);
// Step 5: This must be called for all newly created objects
// in deepClone(). It is turned off by endDeepClone()
// after it has translated the references to their
// new values.
//
pClone->setAcDbObjectIdsInFlux();
// Step 6: Add the new information to the ID map. We can use
// the ID pair started above.
//
idPair.setValue(pClonedObject->objectId());
idPair.setIsCloned(Adesk::kTrue);
idMap.assign(idPair);
// Step 7: Using the filer list created above, find and clone
// any owned objects.
//
AcDbObjectId id;
while (filer.getNextOwnedObject(id)) {
AcDbObject *pSubObject;
AcDbObject *pClonedSubObject;
// Some object’ s references may be set to NULL,
// so don’t try to clone them.
//
if (id == NULL)
continue;
// Open the object and clone it. Note that "isPrimary" is
// set to kFalse here because the object is being cloned,
// not as part of the primary set, but because it is owned
// by something in the primary set.
//
acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead);
pClonedSubObject = NULL;
pSubObject->deepClone(pClonedObject,
pClonedSubObject,
idMap, Adesk::kFalse);
// If this is a kDcInsert context, the objects
// may be "cheap" cloned. In this case, they are
// "moved" instead of cloned. The result is that
// pSubObject and pClonedSubObject will point to
// the same object. Therefore, we only want to close
// pSubObject if it really is a different object
// than its clone.
//
if (pSubObject != pClonedSubObject)
pSubObject->close();
// The pSubObject may either already have been
// cloned, or for some reason has chosen not to be
// cloned. In that case, the returned pointer will
// be NULL. Otherwise, since we have no immediate
// use for it now, we can close the clone.
//
if (pClonedSubObject != NULL)
pClonedSubObject->close();
}
// Leave pClonedObject open for the caller.
//
return Acad::eOk;
}