3 August 2009
Note: The ZIP files are Flex Builder project archives. The starter archive is the completed Part 5 project archive. The solution archive contains the completed code and assets associated with this part. The latter is provided to you to compare against your own completed code.
Welcome to Part 6 of this tutorial series. In this part, you will animate the inventory amounts in the colored bins to count down based on the production rate. The bins will change color when each reaches its threshold value and the clock stops when there is no more inventory or the time runs out.
Note: Parts 1 through 6 focus on teaching Flex development to SAP developers. Part 7 teaches Flex developers how to create a Web Dynpro application. Parts 8 and 9 show both SAP and Flex developers how to integrate the Flex application as a Rich Island into the Web Dynpro application.
In this section, you synchronize the clock animation to the wagon assembly animation by decreasing the bin inventory quantity as the clock counts down. Every 6 seconds (the current production rate) a wagon is created and inventory is decreased in the bins.
_productionRateCounter and data type it to the uint class and assign a value of 0 (zero) to it.private var _productionRateCounter:uint = 0;
The _productionRateCounter variable is incremented each time the timer event is called; currently that is every second. You will programmatically check the value of this variable and decrease inventory at the set production rate (currently every 6 seconds).
timerEventHandler() function in the Script block.partsLeftInBin and data type it to the uint class.partsNeededPerWagon and data type it to the uint class.Note: Remember that these variables are evaluated for each inventory bin. For example, the number of parts needed per wagon for the wheels bin is four while the parts needed per wagon for the axels is two.
stopTimer() function, but still in the conditional statement, reset the _productionRateCounter variable to 0 (zero).else statement, after the current code, increment the _productionRateCounter variable using ++ syntax.private function timerEventHandler(event:TimerEvent):void
{
var partsLeftInBin:uint;
var partsNeededPerWagon:uint;
if (_secondsToCreateAvailableWagons == 0)
{
stopTimer();
_productionRateCounter = 0;
}
else
{
_secondsToCreateAvailableWagons--;
setClockDisplay();
_productionRateCounter++;
}
}
_productionRateCounter variable in the else statement, create another conditional statement that tests whether dividing the _productionRateCounter variable by the _wagonProductionRate is equivalent to 0 (zero) or has a remainder. Use the modulus operator (%).The current _wagonProductionRate variable is set to 6 seconds so you want wagon inventory to decrement every 6 seconds; however, you still need the clock to decrement every second. Since the _productionRateCounter will maintain a running count of seconds, you can divide it by the _wagonProductionRate to check whether the current second is on a 6-second increment.
The modulus operator divides the first variable by the second and gives you the remainder. If the remainder is not zero, then you know that the current second is not on a 6-second increment and you should only update the clock display but not the inventory. If the remainder is zero, then you should update the clock as well as the inventory.
_productionRateCounter++;
if(_productionRateCounter % _wagonProductionRate == 0)
{
}
for loop to loop over the _wagonInventory ArrayCollection instance. In the for statement, create a local iterant named x and data type it to the uint class with a value of 0 (zero). While x is less than _wagonInventory.length, iterate the loop using the x++ syntax.You loop over the data in the ArrayCollection to decrease each bin's inventory.
if(_productionRateCounter % _wagonProductionRate == 0)
{
for(var x:uint = 0; x < _wagonInventory.length; x++)
{
}
}
Quantity of the current index of the _wagonInventory object to the partsLeftInBin variable. Use the getItemAt() function.Parts key of the current index of the _wagonInventory ArrayCollection object to the partsNeededPerWagon variable. Use the getItemAt() function.You create these variables to shorten the variable references for convenience sake. Otherwise this step is not necessary.
if(_productionRateCounter % _wagonProductionRate == 0)
{
for(var x:uint = 0; x < _wagonInventory.length; x++)
{
partsLeftInBin = _wagonInventory.getItemAt(x).Quantity;
partsNeededPerWagon = _wagonInventory.getItemAt(x).Parts;
}
}
partsLeftInBin variable is less than the partsNeededPerWagon variable.partsLeftInBin = _wagonInventory.getItemAt(x).Quantity;
partsNeededPerWagon = _wagonInventory.getItemAt(x).Parts;
if (partsLeftInBin < partsNeededPerWagon)
{
}
stopTimer() function and set the _secondsToCreateAvailableWagons variable to 0._productionRateCounter variable to 0.break keyword.If the inventory is too low to create a wagon, then you must stop the timer and set the clock display and production counter to zero.
if (partsLeftInBin < partsNeededPerWagon)
{
stopTimer();
_secondsToCreateAvailableWagons = 0;
_productionRateCounter = 0
break;
}
else statement that will run if the statement evaluates to false.if (partsLeftInBin < partsNeededPerWagon)
{
. . .
}
else
{
}
partsLeftInBin variable by the partsNeededPerWagon variable using the -= syntax.partsLeftInBin to the _wagonInventory Quantity using the getItemAt() function and x as the index value.refresh() function on _wagonInventory.You decrease each bin inventory by the parts needed per wagon and set the new value for Quantity in the ArrayCollection. You must refresh the data in the ArrayCollection instance.
}
else
{
partsLeftInBin -= partsNeededPerWagon;
_wagonInventory.getItemAt(x).Quantity = partsLeftInBin;
_wagonInventory.refresh();
}
You should see that the clock animation is synchronized with inventory reduction in the colored bins and DataGrid control. Note that the inventory in the colored bins is decremented every 6 seconds. However, if you make a change in the DataGrid control, the clock does not adjust properly.
recalculate() that takes one argument named event with a data type of the CollectionEvent class and with a value of null. The function returns a void data type.private function recalculate(event:CollectionEvent = null):void
{
}
_productionRateCounter to 0, then call the stopTimer() function, call the calculateMaxWagonsPossibleFromInventory() function and finally call the startTimer() function.This function will run when you need to reset the clock display. Remember that the _productionRateCounter variable is a counter that is incremented every second. You call the stopTimer() function, to stop the timer before you use the calculateMaxWagonsPossibleFromInventory() function to start the process of calculating the minutes and seconds on the clock. After that calculation is complete, you start the clock animation again.
private function recalculate(event:CollectionEvent = null):void
{
_productionRateCounter = 0;
stopTimer();
calculateMaxWagonsPossibleFromInventory();
startTimer();
}
startProduction() function.the populateData() function call, add an event listener on the _wagonInventory data that listens for the CollectionEvent.COLLECTION_CHANGE event and calls the recalculate() function.This code will ensure that the recalculate() function is called each time the _wagonInventory ArrayCollection data is changed.
populateData();
_wagonInventory.addEventListener(CollectionEvent.COLLECTION_CHANGE,
recalculate);
Change the quantity for the handles to 100 in the DataGrid control and press Enter. You should see that the clock time adjusts.
In this section, you will allow the user to change the quantity in the TextInput control within the bin and ensure that changes to the inventory quantities in the colored bins are properly reflected in the application display. This will require that you handle the change by updating the _wagonInventory ArrayCollection data. This will ensure that all UI components, like the DataGrid control, that are bound to the ArrayCollection data will reflect the data update.
editable property value to true.<mx:TextInput id="binData"
text="{_wagonInventory.getItemAt(_binPosition).Quantity}"
editable="true"
. . . />
Make a change to a bin TextInput control and press Enter. You should see that the change you made has no effect on the corresponding DataGrid control's quantity or the clock time.
enter event with a value of updateBinInventory().You will create the updateBinInventory() function next.
<mx:TextInput id="binData"
. . .
enter="updateBinInventory()"/>
updateBinInventory() that takes no arguments and has a void return type.private function updateBinInventory():void
{
}
binData text property value to the uint class and assign it to _wagonInventory.getItemAt(_binPosition).Quantity.Data in a text field is always treated as a string. You must cast the string data into whatever data type is appropriate. In this case, you use the uint() function to cast the string data as a uint (unsigned integer) data type to match the Quantity data type.
private function updateBinInventory():void
{
_wagonInventory.getItemAt(_binPosition).Quantity = uint(binData.text);
}
binColorHandler() function to calculate whether the bin color should change.refresh() function of _wagonInventory to update the ArrayCollection data.private function updateBinInventory():void
{
_wagonInventory.getItemAt(_binPosition).Quantity = uint(binData.text);
binColorHandler();
_wagonInventory.refresh();
}
Change a bin quantity to 20 in the DataGrid control and press Enter. Note that the clock time adjusts and the data in the TextInput control changes to match the DataGrid control. Change the same quantity to 50 in the TextInput control and press Enter. Notice that the clock time adjusts again and the data in the DataGrid changes to match the TextInput control.
In this tutorial, you animated the inventory quantities in the colored bins with the clock animation. You also allowed the user to change the inventory quantity in the bins and reflect that change in the both the clock display and DataGrid control.
In Part 7, experienced Flex developers will create the Web Dynpro application and generally familiarize themselves with the NetWeaver ABAP interface. Experienced SAP developers can skip to Part 8, where you will integrate the Rich Island you have built in Parts 1 through 6 into a provided Web Dynpro application.
For your reference, here are all the parts in this series: