| 1 | #include "CubitSimpleAttrib.hpp" |
|---|
| 2 | #include "ToolDataUser.hpp" |
|---|
| 3 | #include "TDUniqueId.hpp" |
|---|
| 4 | #include "CastTo.hpp" |
|---|
| 5 | #include "RefEntity.hpp" |
|---|
| 6 | #include "SDLCADeferredAttribList.hpp" |
|---|
| 7 | #include "DLIList.hpp" |
|---|
| 8 | |
|---|
| 9 | DLIList<CubitAttrib*> CADeferredAttrib::unactuatedCAs; |
|---|
| 10 | SDLCADeferredAttribList CADeferredAttrib::allCADeferredAttribs; |
|---|
| 11 | |
|---|
| 12 | CubitAttrib* CADeferredAttrib_creator(RefEntity* entity, CubitSimpleAttrib *p_csa) |
|---|
| 13 | { |
|---|
| 14 | CADeferredAttrib *new_attrib = NULL; |
|---|
| 15 | |
|---|
| 16 | // Deferred attributes are a special case -- they should only get created |
|---|
| 17 | // when restoring from a file, in which case p_csa should be non-NULL |
|---|
| 18 | if (NULL != p_csa) |
|---|
| 19 | { |
|---|
| 20 | new_attrib = new CADeferredAttrib(entity, p_csa); |
|---|
| 21 | } |
|---|
| 22 | return new_attrib; |
|---|
| 23 | } |
|---|
| 24 | |
|---|
| 25 | |
|---|
| 26 | CADeferredAttrib::~CADeferredAttrib() |
|---|
| 27 | { |
|---|
| 28 | while (allCADeferredAttribs.move_to(this)) |
|---|
| 29 | allCADeferredAttribs.remove(); |
|---|
| 30 | |
|---|
| 31 | delete thisCSA; |
|---|
| 32 | } |
|---|
| 33 | |
|---|
| 34 | CADeferredAttrib::CADeferredAttrib(RefEntity *, CubitSimpleAttrib *csa_ptr) |
|---|
| 35 | : CubitAttrib(NULL) |
|---|
| 36 | { |
|---|
| 37 | init_csa(csa_ptr); |
|---|
| 38 | hasUpdated = CUBIT_TRUE; |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | CubitStatus CADeferredAttrib::init_csa(CubitSimpleAttrib *csa_ptr) |
|---|
| 42 | { |
|---|
| 43 | int csa_type = CGMApp::instance()->attrib_manager()->attrib_type(csa_ptr); |
|---|
| 44 | if (CA_DEFERRED_ATTRIB != csa_type) |
|---|
| 45 | { |
|---|
| 46 | assert(false); |
|---|
| 47 | return CUBIT_FAILURE; |
|---|
| 48 | } |
|---|
| 49 | |
|---|
| 50 | // initialize this according to csa_ptr |
|---|
| 51 | |
|---|
| 52 | // first get the uniqueId off the csa |
|---|
| 53 | csa_ptr->int_data_list()->reset(); |
|---|
| 54 | uniqueId = *csa_ptr->int_data_list()->get(); |
|---|
| 55 | assert(uniqueId > 0); |
|---|
| 56 | |
|---|
| 57 | // now check to see if we have this CADA alreedy; if so, set the |
|---|
| 58 | // delete flag and exit |
|---|
| 59 | CubitBoolean already_have = CUBIT_FALSE; |
|---|
| 60 | if (allCADeferredAttribs.move_to(uniqueId)) { |
|---|
| 61 | do { |
|---|
| 62 | if (allCADeferredAttribs.get_and_step()->equivalent(csa_ptr)) { |
|---|
| 63 | already_have = CUBIT_TRUE; |
|---|
| 64 | break; |
|---|
| 65 | } |
|---|
| 66 | } |
|---|
| 67 | while (!allCADeferredAttribs.is_at_beginning() && |
|---|
| 68 | allCADeferredAttribs.get()->unique_id() == uniqueId); |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | if (already_have) { |
|---|
| 72 | deleteAttrib = CUBIT_TRUE; |
|---|
| 73 | return CUBIT_SUCCESS; |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | // copy the info on the csa; need a new one, since |
|---|
| 77 | // we don't own the original |
|---|
| 78 | thisCSA = csa_from_dcsa(csa_ptr); |
|---|
| 79 | assert(thisCSA != 0); |
|---|
| 80 | |
|---|
| 81 | // add this to the global list |
|---|
| 82 | allCADeferredAttribs.append(this); |
|---|
| 83 | |
|---|
| 84 | return CUBIT_SUCCESS; |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | CubitStatus CADeferredAttrib::actuate() |
|---|
| 88 | { |
|---|
| 89 | // test to see if we can assign this CADA to a new owner; set |
|---|
| 90 | // flag accordingly |
|---|
| 91 | if (assign_to_owner()) { |
|---|
| 92 | hasActuated = CUBIT_TRUE; |
|---|
| 93 | return CUBIT_SUCCESS; |
|---|
| 94 | } |
|---|
| 95 | else return CUBIT_FAILURE; |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | CubitStatus CADeferredAttrib::update() |
|---|
| 99 | { |
|---|
| 100 | // the hasUpdated flag should always be true by the time |
|---|
| 101 | // we get here, since the function that put this CA on the |
|---|
| 102 | // owning entity set the flag |
|---|
| 103 | assert(hasUpdated == CUBIT_TRUE); |
|---|
| 104 | return CUBIT_SUCCESS; |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | CubitStatus CADeferredAttrib::reset() |
|---|
| 108 | { |
|---|
| 109 | // do nothing; this CA manages its own duplicates, so no need |
|---|
| 110 | // to worry about them in parent code |
|---|
| 111 | return CUBIT_SUCCESS; |
|---|
| 112 | } |
|---|
| 113 | |
|---|
| 114 | CubitSimpleAttrib* CADeferredAttrib::cubit_simple_attrib() |
|---|
| 115 | { |
|---|
| 116 | return new CubitSimpleAttrib(thisCSA); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | CubitStatus CADeferredAttrib::assign_to_owner(CubitAttribUser *owner) |
|---|
| 120 | { |
|---|
| 121 | //- looks for an entity with the right uid, assigns itself to |
|---|
| 122 | //- that entity if found |
|---|
| 123 | |
|---|
| 124 | if (uniqueId == 0) return CUBIT_FAILURE; |
|---|
| 125 | |
|---|
| 126 | if (owner == NULL) { |
|---|
| 127 | ToolDataUser *tdu = TDUniqueId::find_td_unique_id(uniqueId); |
|---|
| 128 | owner = CAST_TO(tdu, CubitAttribUser); |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | if (owner == NULL) return CUBIT_FAILURE; |
|---|
| 132 | |
|---|
| 133 | // ok, we have an owner; create a new CA using the csa, assigning |
|---|
| 134 | // it to the ref entity |
|---|
| 135 | RefEntity *ref_ent = CAST_TO(owner, RefEntity); |
|---|
| 136 | assert (ref_ent != 0); |
|---|
| 137 | |
|---|
| 138 | // CubitAttrib *new_cubit_attrib = |
|---|
| 139 | // CGMApp::instance()->attrib_manager()->create_cubit_attrib(thisCSA, ref_ent); |
|---|
| 140 | int attrib_type = CGMApp::instance()->attrib_manager()->attrib_type(thisCSA); |
|---|
| 141 | CubitAttrib *new_cubit_attrib = |
|---|
| 142 | CGMApp::instance()->attrib_manager()->create_cubit_attrib(attrib_type, ref_ent, thisCSA); |
|---|
| 143 | |
|---|
| 144 | // now remove this CADA from the global list and add the new CA |
|---|
| 145 | // to the unactuated list |
|---|
| 146 | allCADeferredAttribs.move_to(this); |
|---|
| 147 | allCADeferredAttribs.remove(); |
|---|
| 148 | |
|---|
| 149 | // new attribute might be NULL, if there was already one there |
|---|
| 150 | if (NULL != new_cubit_attrib) unactuatedCAs.append(new_cubit_attrib); |
|---|
| 151 | |
|---|
| 152 | // ok, all done |
|---|
| 153 | |
|---|
| 154 | deleteAttrib = CUBIT_TRUE; |
|---|
| 155 | return CUBIT_SUCCESS; |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | CubitStatus CADeferredAttrib::get_deferred_attribs(const int uid, |
|---|
| 159 | SDLCADeferredAttribList &cada_list) |
|---|
| 160 | { |
|---|
| 161 | // find a deferred attribute for the entity with the uid passed in |
|---|
| 162 | cada_list.clean_out(); |
|---|
| 163 | if (allCADeferredAttribs.move_to(uid)) { |
|---|
| 164 | do |
|---|
| 165 | cada_list.append(allCADeferredAttribs.get_and_step()); |
|---|
| 166 | while (!allCADeferredAttribs.is_at_beginning() && |
|---|
| 167 | allCADeferredAttribs.get()->unique_id() == uid); |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | if (cada_list.size() > 0) return CUBIT_SUCCESS; |
|---|
| 171 | else return CUBIT_FAILURE; |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | CubitStatus CADeferredAttrib::cleanup_cadas(const CubitBoolean from_constructor, |
|---|
| 175 | const CubitBoolean after_geom_changes) |
|---|
| 176 | { |
|---|
| 177 | CubitStatus status = CUBIT_FAILURE; |
|---|
| 178 | |
|---|
| 179 | if (CUBIT_TRUE == from_constructor) |
|---|
| 180 | status = CADeferredAttrib::cleanup_cadas_private(CUBIT_TRUE, CUBIT_FALSE); |
|---|
| 181 | |
|---|
| 182 | // exit if we're not to actuate for after_geom_changes |
|---|
| 183 | if (CUBIT_TRUE == after_geom_changes) |
|---|
| 184 | status = CADeferredAttrib::cleanup_cadas_private(CUBIT_FALSE, CUBIT_TRUE); |
|---|
| 185 | |
|---|
| 186 | return status; |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | CubitStatus CADeferredAttrib::cleanup_cadas_private(const CubitBoolean from_constructor, |
|---|
| 190 | const CubitBoolean after_geom_changes) |
|---|
| 191 | { |
|---|
| 192 | // moves between the global CADA list and the unactuated list: |
|---|
| 193 | // |
|---|
| 194 | // 1. tries to actuate all CADAs on unactuated list |
|---|
| 195 | // 2. tries to assign_to_owner all CADAs on global list |
|---|
| 196 | // |
|---|
| 197 | // after each of these steps, if anything happened, the loop is |
|---|
| 198 | // repeated |
|---|
| 199 | // this function should be called as part of the auto actuate process |
|---|
| 200 | |
|---|
| 201 | // first call for from_constructor and !after_geom_changes attributes |
|---|
| 202 | CubitBoolean done = CUBIT_FALSE; |
|---|
| 203 | CubitStatus did_something = CUBIT_FAILURE; |
|---|
| 204 | |
|---|
| 205 | while (done == CUBIT_FALSE) { |
|---|
| 206 | done = CUBIT_TRUE; |
|---|
| 207 | int i; |
|---|
| 208 | for (i = unactuatedCAs.size(); i > 0; i--) { |
|---|
| 209 | CubitAttrib *attrib = unactuatedCAs.get(); |
|---|
| 210 | if( attrib == 0 ) |
|---|
| 211 | continue; |
|---|
| 212 | |
|---|
| 213 | // check the auto actuate flag for this CA; since this function |
|---|
| 214 | // is only called from the auto actuating process, we don't need |
|---|
| 215 | // to check whether the user requested that this attribute be actuated |
|---|
| 216 | if (attrib->auto_actuate_flag() == CUBIT_TRUE && |
|---|
| 217 | (!from_constructor || attrib->actuate_in_constructor()) && |
|---|
| 218 | (after_geom_changes || !attrib->actuate_after_geom_changes())) |
|---|
| 219 | { |
|---|
| 220 | |
|---|
| 221 | // if the attribute has already actuated, but is still in our list, |
|---|
| 222 | // count it as doing something |
|---|
| 223 | if ( /*attrib->has_actuated() || */ |
|---|
| 224 | attrib->actuate() == CUBIT_SUCCESS) { |
|---|
| 225 | PRINT_DEBUG_90("Actuated a CADA of type %s\n", |
|---|
| 226 | attrib->att_internal_name()); |
|---|
| 227 | did_something = CUBIT_SUCCESS; |
|---|
| 228 | done = CUBIT_FALSE; |
|---|
| 229 | unactuatedCAs.remove(); |
|---|
| 230 | } |
|---|
| 231 | else unactuatedCAs.step(); |
|---|
| 232 | } |
|---|
| 233 | else unactuatedCAs.step(); |
|---|
| 234 | } |
|---|
| 235 | |
|---|
| 236 | if (done == CUBIT_TRUE) break; |
|---|
| 237 | |
|---|
| 238 | // if we did something in the previous loop, some of our CADAs might |
|---|
| 239 | // now have owners; check and see |
|---|
| 240 | for (i = allCADeferredAttribs.size(); i > 0; i--) { |
|---|
| 241 | CADeferredAttrib *cada = allCADeferredAttribs.get_and_step(); |
|---|
| 242 | if (cada->assign_to_owner() == CUBIT_SUCCESS) { |
|---|
| 243 | PRINT_DEBUG_90("Assigned a CADA to a new owner in CADA::cleanup_cadas\n"); |
|---|
| 244 | did_something = CUBIT_SUCCESS; |
|---|
| 245 | done = CUBIT_FALSE; |
|---|
| 246 | } |
|---|
| 247 | } |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | // if there wasn't anthing to do in the first place, we didn't |
|---|
| 251 | // really fail |
|---|
| 252 | if (did_something == CUBIT_FAILURE && unactuatedCAs.size() == 0) |
|---|
| 253 | did_something = CUBIT_SUCCESS; |
|---|
| 254 | |
|---|
| 255 | return did_something; |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | CubitStatus CADeferredAttrib::owner_created(RefEntity *new_owner, const int uid) |
|---|
| 259 | { |
|---|
| 260 | // for a newly created ref entity, assigns any CADA with the same uid to the |
|---|
| 261 | // new entity |
|---|
| 262 | |
|---|
| 263 | // get any CADAs with the same uid |
|---|
| 264 | SDLCADeferredAttribList attrib_list; |
|---|
| 265 | get_deferred_attribs(uid, attrib_list); |
|---|
| 266 | |
|---|
| 267 | // now assign them to the owner |
|---|
| 268 | for (int i = attrib_list.size(); i > 0; i--) |
|---|
| 269 | attrib_list.get_and_step()->assign_to_owner(new_owner); |
|---|
| 270 | |
|---|
| 271 | if (attrib_list.size() > 0) return CUBIT_SUCCESS; |
|---|
| 272 | else return CUBIT_FAILURE; |
|---|
| 273 | } |
|---|
| 274 | /* |
|---|
| 275 | CubitBoolean CADeferredAttrib::is_match(CubitSimpleAttrib *csa_ptr, |
|---|
| 276 | const int uid) |
|---|
| 277 | { |
|---|
| 278 | //- returns true if the simple attribute is deferred type and matches |
|---|
| 279 | //- uid |
|---|
| 280 | assert(csa_ptr && uid > 0); |
|---|
| 281 | csa_ptr->string_data_list()->reset(); |
|---|
| 282 | csa_ptr->string_data_list()->step(); |
|---|
| 283 | csa_ptr->int_data_list()->reset(); |
|---|
| 284 | if (!strcmp(csa_ptr->string_data_list()->get()->c_str(), |
|---|
| 285 | CGMApp::instance()->attrib_manager()->att_internal_name(CA_DEFERRED_ATTRIB)) && |
|---|
| 286 | *csa_ptr->int_data_list()->get() == uid) |
|---|
| 287 | return CUBIT_TRUE; |
|---|
| 288 | else |
|---|
| 289 | return CUBIT_FALSE; |
|---|
| 290 | } |
|---|
| 291 | */ |
|---|
| 292 | |
|---|
| 293 | |
|---|
| 294 | CubitSimpleAttrib *CADeferredAttrib::csa_from_dcsa(CubitSimpleAttrib *csa_ptr, |
|---|
| 295 | const int uid) |
|---|
| 296 | { |
|---|
| 297 | |
|---|
| 298 | //- given a deferred csa, convert it to a normal csa by removing |
|---|
| 299 | //- first type string and first int; if first int doesn't match |
|---|
| 300 | //- uid passed in, NULL is returned |
|---|
| 301 | assert(csa_ptr != 0); |
|---|
| 302 | |
|---|
| 303 | csa_ptr->string_data_list()->reset(); |
|---|
| 304 | if (strcmp(csa_ptr->string_data_list()->get()->c_str(), |
|---|
| 305 | CGMApp::instance()->attrib_manager()->att_internal_name(CA_DEFERRED_ATTRIB))) |
|---|
| 306 | // csa isn't deferred type - return |
|---|
| 307 | return NULL; |
|---|
| 308 | |
|---|
| 309 | csa_ptr->int_data_list()->reset(); |
|---|
| 310 | if (uid != 0 && *csa_ptr->int_data_list()->get() != uid) |
|---|
| 311 | // csa uid doesn't match - return |
|---|
| 312 | return NULL; |
|---|
| 313 | |
|---|
| 314 | // else we have a match - build new csa |
|---|
| 315 | CubitSimpleAttrib *new_csa = new CubitSimpleAttrib(csa_ptr); |
|---|
| 316 | |
|---|
| 317 | new_csa->string_data_list()->reset(); |
|---|
| 318 | delete new_csa->string_data_list()->remove(); |
|---|
| 319 | |
|---|
| 320 | new_csa->int_data_list()->reset(); |
|---|
| 321 | delete new_csa->int_data_list()->remove(); |
|---|
| 322 | |
|---|
| 323 | return new_csa; |
|---|
| 324 | } |
|---|
| 325 | |
|---|
| 326 | bool CADeferredAttrib::add_unactuated_ca(CubitAttrib *ca_ptr) |
|---|
| 327 | { |
|---|
| 328 | return (CUBIT_TRUE == unactuatedCAs.append_unique(ca_ptr) ? true : false); |
|---|
| 329 | } |
|---|
| 330 | |
|---|
| 331 | bool CADeferredAttrib::remove_unactuated_ca( CubitAttrib* ca_ptr ) |
|---|
| 332 | { |
|---|
| 333 | int item_index = unactuatedCAs.where_is_item( ca_ptr ); |
|---|
| 334 | if( item_index >= 0 ) |
|---|
| 335 | { |
|---|
| 336 | // This is often called when other code is stepping through |
|---|
| 337 | // the list, so don't change the current list position. |
|---|
| 338 | int curr_index = unactuatedCAs.get_index(); |
|---|
| 339 | int step = item_index - curr_index; |
|---|
| 340 | unactuatedCAs.step( step ); |
|---|
| 341 | assert( unactuatedCAs.get() == ca_ptr ); |
|---|
| 342 | unactuatedCAs.change_to(0); |
|---|
| 343 | unactuatedCAs.step( -step ); |
|---|
| 344 | assert( unactuatedCAs.get_index() == curr_index ); |
|---|
| 345 | return true; |
|---|
| 346 | } |
|---|
| 347 | else |
|---|
| 348 | return false; |
|---|
| 349 | } |
|---|