MXNAFeedView.as

Here is the next class from the MXNA Web Service sample app. This is the MXNAFeedView class, and is the main (and currently only) view class of the app.

It contains most of the UI elements for selecting and displaying categories and feeds.

You can also view the MXNAAppController class.

I will post the rest of the classes as I comment and finish them.

As usual, if you have any suggestions or questions, post them in the comments.


[code]import mx.controls.ComboBox;import mx.controls.DataGridimport mx.controls.TextArea;import com.macromedia.mesh.events.EventProxy;import com.macromedia.mxna.app.MXNARankingCell;/*This class is the main view application. It contains the primaryUI elements for displaying information to the user.*/class com.macromedia.mxna.app.MXNAFeedView extends MovieClip{/* Declar functions that EventDispatcher adds */private var dispatchEvent:Function;public var addEventListener:Function;public var removeEventListener:Function;/* Components used in class */private var category_cb:ComboBox;private var feedDG:DataGrid;private var feedField:TextArea;private var titleField:TextArea;private var urlField:TextArea;/* used to load ranking stars into */private var loadingClip:MovieClip;/*These are proxies so we can direct the events to individual methodsand so we can run them in the scope of this class*/private var categoryProxy:EventProxy;private var feedGridProxy:EventProxy;/* The enabled state of the class */private var isEnabled:Boolean;/*We have to store the current direction of the ranking sortso we can manually sort it*/private var rankingSortASC:Boolean;/* Array of Months. This should really be in some */private var MONTHS:Array = ["January","February","March","Arpil","May","June","July","August","September","October","November","December"];/* Constructor. Most initialization done in onLoad */public function MXNAFeedView(){/* initialize this class to broadclass events using EventDispatcher*/mx.events.EventDispatcher.initialize(this);}/*called when the class / symbol is loaded on stage. Most of theinitialization is done here*/private function onLoad():Void{isEnabled = true;rankingSortASC = true;/*Create a proxy so the change event from the category ComboBoxcan go to its own method, and be called in the scope ofthis class*/categoryProxy = new EventProxy(this, "onCategorySelect");category_cb.addEventListener("change", categoryProxy);//show up to 10 items at a time in the combo box dropdowncategory_cb.rowCount = 10;//only show the following columns in the datagridfeedDG.columnNames = ["title", "name", "ranking"];//size the columns in the datagridfeedDG.getColumnAt(0).width = feedDG._width - 200;feedDG.getColumnAt(1).width = 105;feedDG.getColumnAt(2).width = 95;//use a custom cell renderer for the ranking column.feedDG.getColumnAt(2).cellRenderer = "MXNARankingCell";//don't sort ranking column automaticallyfeedDG.getColumnAt(2).sortOnHeaderRelease = false;//catch the headerRelease event so we can sort the ranking column manuallyfeedDG.addEventListener("headerRelease", this);/*Create a proxy so the change event from the datagridcan go to its own method, and be called in the scope ofthis class*/feedGridProxy = new EventProxy(this, "onFeedGridSelect");feedDG.addEventListener("change", feedGridProxy);//initialize feed data TextAreafeedField.html = true;feedField.editable = false;//initialize feed title TextAreatitleField.html = true;titleField.editable = false;titleField.wordWrap = false;//no bordertitleField.setStyle("borderStyle", "none");//initialize feed url TextAreurlField.html = true;urlField.editable = false;urlField.wordWrap = false;//no borderurlField.setStyle("borderStyle", "none");}//setter for setting the enabled propertypublic function set enabled(enabled:Boolean){isEnabled = enabled;category_cb.enabled = enabled;feedDG.enabled = enabled;feedField.enabled = enabled;titleField.enabled = enabled;urlField.enabled = enabled;}//getter for enabled propertypublic function get enabled():Boolean{return isEnabled;}//populates the ComboBox with categories//Takes on optional second parameter that specifies which field the label//is stored withinpublic function setCategories(categories:Array, labelField:String):Void{if(labelField != undefined){category_cb.labelField = labelField;}category_cb.dataProvider = categories;}//setter for the feeds to be displayed within the DataGridpublic function set dataProvider(dp:Array){//clear all TextArea fieldsclearFields();//set the dataprovider for the DataGridfeedDG.dataProvider = dp;//select the first row in the data gridfeedDG.selectedIndex = 0;//since the previous line does not trigger the change event, we need to//manually call the displayFeed method, to display the info on the first//rowdisplayFeed(feedDG.selectedItem);}//simple methods that clears the TextArea and ranking starsprivate function clearFields(Void):Void{titleField.text = "";feedField.text = "";urlField.text = "";loadingClip.star.removeMovieClip();}//simple method to format a Date object into the format we want to displayprivate function formatDate(d:Date):String{//January 25, 2004��11:30 AMvar hours:Number = d.getHours();var timeOfDay:String = "AM";if(hours > 12){timeOfDay = "PM";hours = hours - 12;}//note, this will only work up until 2010var year:Number = d.getYear() - 100;//TODO: the minutes to be formatted when it is 1-9.var out:String = MONTHS[d.getMonth()] + " " + d.getDate() + ", " +"200" + year + " " + hours + ":" + d.getMinutes() +" " + timeOfDay + " UTC";return out;}//takes an item from the DataGrid, and display the specific informationprivate function displayFeed(feedItem:Object):Void{/*feedItem contains the following properties:websiteUrltitlelinkexcerptdateAggregatedrankingclickscategorynameid*///bail if undefinedif(feedItem == undefined){return;}//title fieldtitleField.text = "" + createLink(feedItem.title, feedItem.link, true) + " (" +createLink(feedItem.name, feedItem.websiteUrl, true) + ")";//feed fieldfeedField.text = "" + formatDate(feedItem.dateAggregated) + "
" +feedItem.excerpt + "

" + createLink("Link...", feedItem.link, true, true);//urlFieldurlField.text = createLink(feedItem.link, feedItem.link, true, true);//ranking is passed in as a stringvar star:Number = Number(feedItem.ranking);//normally, we only rank items within the last 24 hours. Items older than//24 hours rank 0, and dont show any graphic. However, this was confusing//in the UI, so we will give items older than 24 hours 0 stars.//Note that this does not necessarily mean they have no clicks, but//rather that they are older than 24 hours.//TODO : Fix this. Maybe a different graphic.if(star < 1){star = 1;}//display the appropriate star symbolloadingClip.attachMovie("star" + star, "star", 998);}//simple method that generates HTML code for a link//optionally takes two extra parameters that specify whether to//color(highlight) and underline the link.////TODO : Look into using style sheetsprivate function createLink(title:String, link:String,highlight:Boolean, underline:Boolean):String{//default highlight to falseif(highlight == undefined){highlight = false;}//default underline to falseif(underline == undefined){underline = false;}//create the linkvar out:String = "" + title + "";//see if we need to add a font tagif(highlight){out = "" + out + "";}//see if we need to add underline tagsif(underline){out = "" + out + "";}return out;}/******** UI Event Handlers *********///broadcast by ComboBox when user selects an item in the comboprivate function onCategorySelect(eventObj:Object):Void{//get the selected categoryvar category:String = category_cb.selectedItem[category_cb.labelField];//broadcast an event that a category has been selecteddispatchEvent({type:"onSelectCategory", category:category});}//broadcast by the DataGrid when the user selects a rowprivate function onFeedGridSelect(eventObj:Object){//get and display the item from the selected rowvar item:Object = feedDG.selectedItem;displayFeed(item);}//broadcast by the DataGrid when the user releases from click one of the//column headersprivate function headerRelease(eventObj:Object){//we only care if they clicked the ranking column, so ignore clicks//from other columsn//TODO : columnIndex should be put in a CONSTANTif(eventObj.columnIndex != 2){return;}//reverse the rankingrankingSortASC = !rankingSortASC;//figure out which way to sort, and then call the appropriate function//TODO : figure out if there is a better way to do thisvar sortFunc = (rankingSortASC)? sortGridByRankingASC : sortGridByRankingDESC;//sort the DGfeedDG.sortItems(sortFunc);}//custom sorting functions for the ranking columnprivate function sortGridByRankingASC(a,b){return Number(a.ranking) > Number(b.ranking);}private function sortGridByRankingDESC(a,b){return Number(a.ranking) < Number(b.ranking);}}[/code]