PDA

View Full Version : y coordinate gets set to height of canvas upon destroy() of object


kmeixner
11-10-2008, 10:57 AM
I have the following class defined as a kinda fancy set object or "collection" that stores items in an array and has some useful methods defined for managing them (add, delete, insert at index, etc):

<library>

<!---
Fancy array list manager.
-->
<class name="collection">

<!-- *** ATTRIBUTES *** -->

<!--- @keywords private -->
<!--- @param array itemlist: Array of listed items -->
<attribute name="itemlist" />

<!--- *** METHODS *** -->

<!--- @returns number(int) the number of items in list -->
<method name="getNumItems">
if (this['itemlist']){
return this.itemlist.length;
}
else {
return 0;
}
</method>

<!---@returns <class> the item at the given index or null if undefined-->
<method name="getItemAtIndex" args="index">
return this.itemlist[index];
</method>

<!---
Add item to list.
@param <class> item: add item to end of list
-->
<method name="addItemToEnd" args="item">
this.itemlist.push(item);
</method>

<!---
This will insert the given item into the list at the given index. Other
items in the list will be shifted down the list.

@param <class> item: item to be inserted into list
@param number(int) index: index to insert item at
-->
<method name="insertItemAtIndex" args="item, index">
this.itemlist.splice(index, 0, item); // Inserts item at index 'index'
</method>

<!---
Remove instance(s) of item from list.
@param <class> item: item to be removed.

@return <class> item removed from 'itemlist'
-->
<method name="removeItem" args="item">
<![CDATA[

// Note: must go backwards since next element will be moved up in list
// when previous element is deleted
for (var i=(itemlist.length-1); i>=0; i--){

if (this.itemlist[i] === item)
return removeItemAtIndex(i); // remove instance(s) of item from array

}

]]>
</method>
<!---
Destroys instance(s) of given item in list.

@param <class> item: item to be destroyed
-->
<method name="destroyItem" args="item">
<![CDATA[

// Note: must go backwards since next element will be moved up in list
// when previous element is deleted
for (var i=(itemlist.length-1); i>=0; i--){

if (this.itemlist[i] === item){
// destroy instance(s) of item and remove array references
this.destroyItemAtIndex(i);
}

}

]]>
</method>

<!---
Removes itemlist array element at given index.
@param number(int) index: index of element to remove.
@return <class> item removed from 'itemlist'
-->
<method name="removeItemAtIndex" args="index">
if ($debug) Debug.write('*!* WARNING *!*: collection.removeItemAtIndex(): Calling the destroy() method on an object returned by this method has been known to result in the Y coordinate of objects getting set to the height of the OpenLaszlo application for unknown reasons.');
var arrVal = this.itemlist.splice(index, 1);
return arrVal[0]; // Returns value of item removed
</method>

<!---
Destroys item at given index and removes reference to it
@param number(int) index: the index of the item to destroy
-->
<method name="destroyItemAtIndex" args="index">
if ($debug) Debug.write('*!* WARNING *!*: collection.destroyItemAtIndex(): Calling this method has been known to result in the Y coordinate of objects getting set to the height of the OpenLaszlo application for unknown reasons.');
var arrVal = this.itemlist.splice(index,1); // remove array element at index
arrVal[0].destroy(); // destroy object removed
</method>

<!--- This will clear the list set it to null -->
<method name="removeAllItems">

// Note: must go backwards since next element will be moved up in list
// when previous element is deleted
for (var i=(itemlist.length-1); i>=0; i--)
removeItemAtIndex(i);

</method>

<!---
Destroys all items in list leaving and empty array.
-->
<method name="destroyAllItems">
<![CDATA[

// Note: must go backwards since next element will be moved up in list
// when previous element is deleted
for (var i=(itemlist.length-1); i>=0; i--){
this.destroyItemAtIndex(i);
}

]]>
</method>

<!---
@param <class> item: item to return array index for
@return number(int): array index of item (starting at 0), -1 if not found
-->
<method name="getIndexOfItem" args="item">
<![CDATA[

for (var i=0; i<= itemlist.length-1; i++){

if (this.itemlist[i] == item)
return i;

}

return -1; // returned if item is not found in list

]]>
</method>

<!---
Moves item up one index in the list.

@return <class>: moved item upon success
@return string "topitem": if given item is already at top of list
@return string "notfound": if given item was not found in list
-->
<method name="moveItemUpOne" args="item">
<![CDATA[

index = this.getIndexOfItem(item);

if (index >= 0 && index <= (this.getNumItems()-1)){
var itemtemp = this.itemlist.splice(index,1);
this.itemlist.splice((index+1),0, itemtemp[0]);

return itemlist[(index+1)];
}
else if (index >= (this.getNumItems()-1)){
return "topitem";
}
else { // item = -1, not found in list
return "notfound";
}

]]>
</method>

<!---
Moves item at index up one index in the list.

@return <class>: moved item upon success
@return string "bottomitem": if given item is already at bottom of list
@return string "notfound": if given item was not found in list
-->
<method name="moveItemAtIndexUpOne" args="index">
<![CDATA[
if (index >= 0 && index <= (this.getNumItems()-1) ){
return this.moveItemUpOne(this.getItemAtIndex(index));
}
else {
return "notfound";
}
]]>
</method>

<!---
Moves item down one index in the list.

@return <class>: moved item upon success
@return string "bottomitem": if given item is already at bottom of list
@return string "notfound": if given item was not found in list
-->
<method name="moveItemDownOne" args="item">
<![CDATA[

index = this.getIndexOfItem(item);

if (index > 0 && index <= (this.getNumItems()-1)){
var itemtemp = this.itemlist.splice(index,1);
this.itemlist.splice((index-1),0, itemtemp[0]);

return itemlist[(index-1)];
}
else if (index === 0){
return "bottomitem";
}
else { // item = -1, not found in list
return "notfound";
}

]]>
</method>

<!---
Moves item at index down one index in the list.

@return <class>: moved item upon success
@return string "bottomitem": if given item is already at bottom of list
@return string "notfound": if given item was not found in list
-->
<method name="moveItemAtIndexDownOne" args="index">
<![CDATA[
if (index >= 0 && index <= (this.getNumItems()-1) ){
return this.moveItemDownOne(this.getItemAtIndex(index));
}
else {
return "notfound";
}
]]>
</method>

<!---
This will move the item at iFromIndex to index iToIndex

@param number iFromIndex: the index of the item to be moved
@param number iToIndex: the destination index
-->
<method name="moveItem" args="iFromIndex, iToIndex">
<![CDATA[

// LAYER MOVING:

var iMaxIndex = (this.getNumItems()-1);
if (0 <= iFromIndex && iFromIndex <= iMaxIndex
&&
0 <= iToIndex && iToIndex <= iMaxIndex
&&
iFromIndex != iToIndex
)
{
var objItem = this.itemlist[iFromIndex];

if (iFromIndex > iToIndex){

// CASE I: move to lower position:
this.itemlist.splice(iFromIndex, 1); // remove item
this.itemlist.splice(iToIndex, 0, objItem); // re-insert item
}
else { // iFromIndex < iToIndex

// CASE II: move to higher position:
this.itemlist.splice(iFromIndex, 1); // remove item
this.itemlist.splice(iToIndex, 0, objItem); // re-insert item
}

return; // nothing else to do
}

// ERROR HANDLING: (only reached if code above not executed):

if ($debug){ // this code is only compiled in debug mode

if (iFromIndex == iToIndex)
Debug.write('collection.moveItem(): WARNING: Received request to move an item to the index it is already at, request ignored.');

if (iFromIndex > iMaxIndex)
Debug.write('collection.moveItem(): WARNING: Received iFromIndex greater than last item index in list.');

if (iToIndex > iMaxIndex)
Debug.write('collection.moveItem(): WARNING: Received iToIndex greater than last item index in list.');

if (iFromIndex < 0)
Debug.write('collection.moveItem(): WARNING: Received iFromIndex that is less than 0.');

if (iToIndex < 0)
Debug.write('collection.moveItem(): WARNING: Received iToIndex that is less than 0.');

}

]]>
</method>

<!-- *** EVENT HANDLERS *** -->


<!--- @keywords private -->
<!--- initializes this.itemlist as an array -->
<handler name="oninit">
// instantiate itemlist as an array:
this.itemlist = new Array();
</handler>

</class>

</library>

Now this class is used to store some references to some visible objects in the application that may be later removed from the "collection" and then deleted via their destroy() method. For some reason when the destroy() method is called on one of these visible objects, sometimes the y coordinates of all the other objects in the "collection.itemlist[]" get their y coordinate set to the height of the application (ie: canvas.height). This occurs even if I call the destroy() method on an object that used to be in the "collection" but is no longer referenced in the collection.

Does anyone see a design flaw in my class above that can cause this to happen?

I am using OpenLaszlo 3.3.4 compiled to SWF8.

Thanks,

Kevin

rcyeager
11-19-2008, 07:37 AM
Can you provide a complete sample that demonstrates the issue?

Robert Yeager
http://www.qrowd.com
http://www.cooqy.com

kmeixner
11-19-2008, 11:37 AM
Thanks rcyeager for your reply,

I have noticed that when you create an OpenLaszlo view (or subclass) it seems to start with its y coordinate set to canvas.height, so I suspect that somewhere in my code something is getting recreated without the y value getting set to its proper value possibly.

My application is large (64000+ lines) and I haven't been able to narrow down the exact location in the code that causes this problem. For now I just have a workaround where I backup the values in a temporary array before inserting or deleting an item from my collection class and check and see if the values have been incorrectly changed afterward and fix them if they have.

If I do find an example that demonstrates the problem I will post it here, for now I am too busy fixing other bugs and implementing some other features in our application requested by some potential investors and customers so it will have to wait for a bit.

Kevin