예제 #1
0
// 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
        // NamedObject 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 which
        // are refered 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.   So, first we must find out if
        // the destination NamedObjects dictionary has
        // our dictionary.
        //
        AcDbDictionary *pDestNamedDict;
        pTo->getNamedObjectsDictionary(pDestNamedDict,
                                       AcDb::kForWrite);

        // Since INSERT does not clone the destination
        // NamedObjects dictionary, we can use getAt()
        // on it.
        //
        es = pDestNamedDict->getAt(kpDictionary, dictId);

        // If our dictionary does not yet exist in the
        // NamedObjects 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 objectIds 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
            // idPairs into the idMap 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 annonymous entry. 
            // The setAt() method will automatically append
            // a unique identifier to each name beginning
            // with "*".  It will become something like,
            // "*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();
}
void
ArxDbgAppEditorReactor::beginDeepCloneXlation(
                            AcDbIdMapping& idMap, Acad::ErrorStatus* es)
{
    m_didTheseDicts.setLogicalLength(0);    // reset the dictionaries we have processed

    AcDbDatabase* origDb;
    AcDbDatabase* destDb;
    idMap.origDb(origDb);
    idMap.destDb(destDb);

    AcDbObject* clonedObj;
    AcDbObject* objToClone;

		// we catch this event so that we can wblock objects that are not entities.
		// This happens from the class ArxDbgUiTdcWblockClone where you are allowed
		// to pick non-entities to wblock to a new/existing drawing.  AcDbDatabase::wblock()
		// only allows entities to be in the set of objects passed to it, but you
		// can manually wblockClone them yourself here.
    if (idMap.deepCloneContext() == AcDb::kDcWblock) {
			// see what non-entity objects we have to clone by hand.
		AcDbObjectIdArray handCloneObjects;
		m_cloneSet.getObjectsForDatabase(origDb, handCloneObjects);
        if (handCloneObjects.isEmpty())
            return;

            // walk through the clone set and try to clone
            // everything.  If something is already cloned,
            // its ok, it won't be cloned again or return an
            // error, it will just set clonedObj to NULL.
        CString str;
        int len = handCloneObjects.length();
        for (int i=0; i<len; i++) {
            clonedObj = NULL;
            if (acdbOpenAcDbObject(objToClone, handCloneObjects[i], AcDb::kForRead) == Acad::eOk) {
                objToClone->wblockClone(destDb, clonedObj, idMap, Adesk::kFalse);
                if (clonedObj != NULL) {
                    acutPrintf(_T("\nArxDbgAppEditorReactor: cloned additional object [%s, %s]"),
                                ArxDbgUtils::objToClassStr(clonedObj),
                                ArxDbgUtils::objToHandleStr(objToClone, str));
                    clonedObj->close();
                }
                objToClone->close();
            }
        }
    }
		// catching this event allows us to correctly bring in our Dictionary Records.
		// If we don't do this, then they will be orphaned.  AutoCAD will not hook up
		// the cloned dictionary records automatically.
    else if ((ArxDbgOptions::m_instance.m_doDictRecordInsertByHand) &&
			 ((idMap.deepCloneContext() == AcDb::kDcInsert) ||
			  (idMap.deepCloneContext() == AcDb::kDcInsertCopy))) {
            // have to manually find all things we are interested in inserting.
            // So, look for all ArxDbgDictRecords, if its a dict record,
            // make sure owner dict is cloned in new database
        AcDbObjectIdArray objIds;
        collectAllDictRecords(origDb, objIds);
        int len = objIds.length();
        for (int i=0; i<len; i++) {
                // find out if object is a dict record
            Acad::ErrorStatus es;
            es = acdbOpenObject(objToClone, objIds[i], AcDb::kForRead);
            if (es == Acad::eOk) {
                acutPrintf("\nArxDbgAppEditorReactor: hand inserting [%s]", ArxDbgUtils::objToClassStr(objToClone));

                    // clone the owner dictionary if one of our dictionary records
                if (objToClone->isKindOf(ArxDbgDbDictRecord::desc()))
                    insertCloneOwnerDict(objToClone->ownerId(), destDb, idMap);

                objToClone->close();
            }
        }
    }
}
// AsdkEdReactor is derived from AcEditorReactor
//
void
AsdkEdReactor::beginDeepCloneXlation(AcDbIdMapping& idMap,
    Acad::ErrorStatus* es)
{
    if (idMap.deepCloneContext() == AcDb::kDcWblock
        && getYorN(_T("Wblock all Text Styles")))
    {
        AcDbDatabase *pOrigDb, *pDestDb;
        if (idMap.origDb(pOrigDb) != Acad::eOk)
            return;
        *es = idMap.destDb(pDestDb);
        if (*es != Acad::eOk)
            return;

        AcDbTextStyleTable *pTsTable;
        *es = pOrigDb->getSymbolTable(pTsTable,
            AcDb::kForRead);
        if (*es != Acad::eOk)
            return;

        AcDbTextStyleTableIterator *pTsIter;
        *es = pTsTable->newIterator(pTsIter);
        if (*es != Acad::eOk) {
            pTsTable->close();
            return;
        }
        AcDbTextStyleTableRecord *pTsRecord;
        AcDbObject *pClonedObj;
        for (; !pTsIter->done(); pTsIter->step()) {
            *es = pTsIter->getRecord(pTsRecord,
                AcDb::kForRead);
            if (*es != Acad::eOk) {
                delete pTsIter;
                pTsTable->close();
                return;
            }
            // We don't need to check for already cloned
            // Records.  If the Text Style is already
            // cloned, wblockClone will return Acad::eOk
            // and pCloneObj will be NULL.
            //
            pClonedObj = NULL;
            *es = pTsRecord->wblockClone(pDestDb,
                pClonedObj, idMap, Adesk::kFalse);
            if (*es != Acad::eOk) {
                pTsRecord->close();
                delete pTsIter;
                pTsTable->close();
                return;
            }
            *es = pTsRecord->close();
            if (*es != Acad::eOk) {
                delete pTsIter;
                pTsTable->close();
                return;
            }
            if (pClonedObj != NULL) {
                *es = pClonedObj->close();
                if (*es != Acad::eOk) {
                    delete pTsIter;
                    pTsTable->close();
                    return;
                }
            }
        }
        delete pTsIter;
        *es = pTsTable->close();
    }
}