Словарь имен объектов
Словарь имен объектов имеет мягкое монопольное использование ее вхождений. Вхождения не таким образом клонировались wblockClone (). Это - до приложения, чтобы копировать те объекты в случае необходимости.
В течение команды INSERT, определенные приложением вхождения в словари имен объектов не скопированы. Приложение должно исполнить желательное клонирование в течение beginDeepCloneXlation() стадия, добавляя объектные ID к карте ID и добавляя новый вход адресата в словарь.
Для подробной информации относительно beginDeepCloneXlation(), см. “ Редактор Функции Уведомления Реактора ” на странице 504.
В течение команды WBLOCK, все ID в первоначальной словари имен объектов принесены к словари имен объектов адресата, но объекты указали, автоматически не скопированы. Если объект, на который ID указывает, не клонировался приложением, ID удален из словаря адресата в течение endDeepClone () трансляция. Снова, приложение должно клонировать объекты в течение beginDeepCloneXlation и добавлять ID к карте ID. Не требоваться добавить новый ID к словари имен объектов адресата, потому что эта задача была выполнена автоматически.
Следующий пример показывает, как Вы могли бы записывать AcEditorReactor:: beginDeepCloneXlation () функция для определяемого пользователем словаря объектов, который помещен в словарь имен объектов. Пример относится только к kDcWblock и kDcInsert контекстам.
// Этот пример демонстрирует способ обработать объекты в словари имен объектов для WBLOCK
и INSERT.
// Наш объект - AcDbDictionary, который назван "AsdkDictionary" в названном словаре объектов, содержащим
// наши заказные объекты.
//
const char *kpDictionary = "AsdkDictionary";
// AsdkNODEdReactor is derived from AcEditorReactor.
//
void
AsdkNODEdReactor::beginDeepCloneXlation( AcDbIdMapping& idMap, Acad::ErrorStatus* pRetStat)
{
Acad::ErrorStatus es;
AcDbObjectId dictId;
if ( idMap.deepCloneContext() != AcDb::kDcWblock && idMap.deepCloneContext() != AcDb::kDcInsert)
return;
// Get the "from" and "to" databases.
//
AcDbDatabase *pFrom, *pTo;
idMap.origDb(pFrom);
idMap.destDb(pTo);
// See if the "from" database has our dictionary, and
// open it. If it doesn’ t have one, we are done.
//
AcDbDictionary *pSrcNamedObjDict;
pFrom->getNamedObjectsDictionary(pSrcNamedObjDict, AcDb::kForRead);
es = pSrcNamedObjDict->getAt(kpDictionary, dictId);
pSrcNamedObjDict->close();
if (es == Acad::eKeyNotFound)
return;
AcDbDictionary *pSrcDict;
acdbOpenObject(pSrcDict, dictId, AcDb::kForRead);
AcDbObject *pClone;
switch (idMap.deepCloneContext()) {
case AcDb::kDcWblock:
// WBLOCK clones all or part of a drawing into a
// newly created drawing. This means that the
// named object dictionary is always cloned, and
// its AcDbObjectIds are in flux. Therefore, you
// cannot use getAt() or setAt() on the dictionary
// in the new database. This is because the
// cloned dictionary references all refer to the
// original objects. During deep clone translation,
// all cloned entries will be translated to the
// new objects, and entries not cloned will be
// "removed" by getting "translated" to NULL.
//
// The cloning of entries in our own dictionary are
// not handled here. If all are to be cloned, then
// call setTreatElementsAsHard(Adesk::kTrue) on the
// dictionary. Otherwise, only those entries that
// are referred to by hard references in other
// wblocked objects will have been cloned via
// those references.
// In this example, we will always write out all of
// the records. Since TreatElementsAsHard is not
// currently persistent, we reset it here each time.
//
pSrcDict->upgradeOpen();
pSrcDict->setTreatElementsAsHard(Adesk::kTrue);
pClone = NULL;
pSrcDict->wblockClone(pTo, pClone, idMap,
Adesk::kFalse);
if (pClone != NULL)
pClone->close();
break;
case AcDb::kDcInsert:
// In INSERT, an entire drawing is cloned, and
// "merged" into a pre-existing drawing. This
// means that the destination drawing may already
// have our dictionary, in which case we have to
// merge our entries into the destination
// dictionary. First we must find out if
// the destination named objects dictionary contains
// our dictionary.
//
AcDbDictionary *pDestNamedDict;
pTo->getNamedObjectsDictionary(pDestNamedDict, AcDb::kForWrite);
// Since INSERT does not clone the destination
// named object dictionary, we can use getAt()
// on it.
//
es = pDestNamedDict->getAt(kpDictionary, dictId);
// If our dictionary does not yet exist in the
// named object dictionary, which is not itself
// cloned, we have to both clone and add our
// dictionary to it. Since dictionary entries are
// ownership references, all of our entries will
// also be cloned at this point, so we are done.
//
if (es == Acad::eKeyNotFound) {
pClone = NULL;
pSrcDict->deepClone(pDestNamedDict, pClone, idMap);
// Unless we have overridden the deepClone()
// of our dictionary, we should expect it to
// always be cloned here.
//
if (pClone == NULL) {
*pRetStat = Acad::eNullObjectId;
break;
}
pDestNamedDict->setAt(kpDictionary, pClone, dictId);
pDestNamedDict->close();
pClone->close();
break;
}
pDestNamedDict->close();
// Our dictionary already exists in the destination
// database, so now we must "merge" the entries
// into it. Since we have not cloned our
// destination dictionary, its object IDs are not in
// flux, and we can use getAt() and setAt() on it.
//
AcDbDictionary *pDestDict;
acdbOpenObject(pDestDict, dictId, AcDb::kForWrite);
AcDbObject *pObj, *pObjClone;
AcDbDictionaryIterator* pIter;
pIter = pSrcDict->newIterator();
for (; !pIter->done(); pIter->next()) {
const char *pName = pIter->name();
pIter->getObject(pObj, AcDb::kForRead);
// If the dictionary contains any references
// and/or other objects have references to it,
// you must either use deepClone() or put the
// ID pairs into the ID map here, so that they
// will be in the map for translation.
//
pObjClone = NULL;
pObj->deepClone(pDestDict, pObjClone, idMap);
// INSERT usually uses a method of cloning
// called CheapClone, where it "moves" objects
// into the destination database instead of
// actually cloning them. When this happens,
// pObj and pObjClone are pointers to the
// same object. We only want to close pObj
// here if it really is a different object.
//
if (pObj != pObjClone)
pObj->close();
if (pObjClone == NULL)
continue;
// If the name already exists in our
// destination dictionary, it must be changed
// to something unique. In this example, the
// name is changed to an anonymous entry.
// The setAt() method will automatically append
// a unique identifier to each name beginning
// with "*", for example: "*S04".
//
if ( pDestDict->getAt(pName, dictId) == Acad::eKeyNotFound)
pDestDict->setAt(pName, pObjClone, dictId);
else
pDestDict->setAt("*S", pObjClone, dictId);
pObjClone->close();
}
delete pIter;
pDestDict->close();
break;
default:
break;
}
pSrcDict->close();
}