ObjectARX, AutoCAD. Среда программирования библиотеки C++

       

Словарь имен объектов


Словарь имен объектов имеет мягкое монопольное использование ее вхождений. Вхождения не таким образом клонировались 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();

}


Содержание раздела