<@doc alias="objectset" hierarchy="GMLDOM"> A logical group of objects. This object implements some methods that help deal with object groups. How does the clone work? The clone operation behaves as follows: First you select a group of elements through the Storyboard's UI either by marking each element, or by marking rectangular area. You copy the selection into the clipboard and then select "paste". alternatively, select "duplicate". The group of visual elements is translated to a group of base objects.
At this point it is also expanded to include additional elements (e.g. members of selected states, links connecting members of selected states)
The selected elements are tested whether each can be cloned, using the canCloneElement. Some elements may be removed from the collection of elements to clone
(e.g. a selected link whose target interactor was not selected) The following events and callbacks are then called: onClone() - to actually clone every member of the selected elements.
This callback is responsible to update a collection that stores the mapping between IDs of the original elements and the newly cloned elements.
This mapping collection is required for the onFixClonedReferences callback.
onFixClonedReferences() - every object goes over its properties and recognizes every property that actually points to another element.
If this element is one of the cloned, it updates the property to point to the newly cloned element.
@GmlObject provides a default implementation for this method, and derived classes may enhance it to deal with specific properties.
onLoad() - the onLoad callback is called for every cloned element, and markes the end of the clone operation.
(c) SAP AG 2003-2006. All rights reserved. Class ObjectSet inherit Object; property objects = {}; constructor(elements) this.objects = elements; end method clone(force , elementsMap) try { var topObjects = this.objects; // the map of top source objects var topCloned = {}; // the map of top cloned objects var allCloned = elementsMap || {}; // the map of all cloned objects (nested) // Step 0: test whether all objects can be cloned var need_repeating = false; if( !(force & #[FORCE_CLONE] )) { do { need_repeating = false; var evt = document.createEventObject(); evt.type = 'canCloneElement'; evt.objectset = topObjects; evt.cancelme = false; evt.cancelall = false; for (var k in topObjects) { evt.object = topObjects[k]; $ENV.fireModelEvent(evt); if (evt.cancelall) return null; if (evt.cancelme) { delete topObjects[k]; need_repeating = true; //break; //break the for //do not break the for. this gives slight optimization. } } } while (need_repeating); } var suppressEvents = $ENV.suppressEvents; $ENV.suppressEvents = true; function run_on_clone(obj,forceCopy) { var newObj = obj.onClone(allCloned,null,forceCopy); delete newObj.parent; delete newObj.unit; topCloned[newObj.id] = newObj; } // step 1: clone the objects. First all non-link elements, then all links for (var k in topObjects) { if (!topObjects[k].isa("gml:Link")) run_on_clone(topObjects[k],force) } for (var k in topObjects) { if (topObjects[k].isa("gml:Link")) run_on_clone(topObjects[k]) } // step 2: fix references between cloned objects for (var k in allCloned) { var elem = allCloned[k]; elem.onFixClonedReferences(allCloned); } // step 3: initialize cloned objects for (var k in allCloned) { var elem = allCloned[k]; if (typeof elem.onLoad == 'function') elem.onLoad(); } $ENV.suppressEvents = suppressEvents; return topCloned; } catch(e) { $ENV.suppressEvents = suppressEvents; var msg='#TEXT[XMSG_FAILED_TO_CLONE_OBJECTS]'; #LOG[4, msg+': '+e.description]; } /* * For properties that contain references to other objects, we check * whether those objects were also copied in this action, and fix the * references. */ //moved to be a member of GmlObject::onFixClonedReferences /* function fixReferences(elem) { var P=elem.Class.properties; for (var name in P) { var prop=P[name], value=elem[name]; if (!elem.hasOwnProperty(name) || !value) continue; switch (prop.type) { case 'pointer': var ptr = allCloned[value.id]; if (ptr) elem[name]=ptr; break; case 'vector': for (var i=0, len=value.length; i