At this point I have a lot more working. Here’s what happened to get to this point.
Once I was able to receive the XML from Flickr containing the list of photos, I had to give it to the TileList. Then the TileList’s
listItemRenderer would take the data and build the URL to display the actual thumbnail image. This turned out to be pretty easy:
- The Gallery component has a setter for
dataProviderwhich expects an Array. This will be the Array of photo information from Flickr.
- The Gallery
dataProvidersetter takes this Array and creates a new ArrayCollection.
[Bindable] public var ac:ArrayCollection; ... // inside of dataProvider setter: ac = new ArrayCollection( ar );
- When the TileList has its dataProvider changed, it causes all of the renderers to receive new dataObjects (the elements of the ArrayCollection).
- The Thumbnail renderer has an override to the setter for
dataObjectwhich causes the Thumbnail to switch to its base state that displays the “Loading” message and hides the image.
dataObjectsetter also forms the URL for the thumbnail and assigns it to the Image.
- When the Image
completeevent triggers, the Thumbnail switches to the image state, displaying the image and hiding the label.
That seems complicated, but the code is pretty clean right now. I know things need to become more complex in the next few days, but for right now, I’m getting to see thumbnails when I enter a tag into the Search Panel.
Not Much Progress
My next task was to get the Progress Bar to work. This is located in the ControlBar area of the Gallery panel and shows how the thumbnails are loading. In the Flex 1.5 version, I made the Gallery itself a source for the Progress Bar. This means that the Gallery dispatches
complete as well as implementing
bytesTotal methods. That was easy with the Gallery being a Tile container. But in my Flex 2 Alpha 1 version, the Gallery is a TileList and I need someway to know when each image has loaded.
I could not find out how a
listItemRenderer knows what control it is a renderer for. In Flex 1.5, each cell renderer was given an object, listOwner. I do not see anywhere in the documentation what this is.
My idea was to tell the listOwner when an image was complete so it could bump up its byte count and be a good source to the Progress Bar.
Since I don’t know how to do that know, I’m leaving out the Progress Bar.
Up to this point the path has been straightforward. Now there are some choices: do I get the Image Viewer (the TitleWindow that displays the larger size image when you click) working? Do I get drag-and-drop working? Do I finish out the Search Panel and add the advanced options? Do I get saving the search history working?
I decided to do a little bit of everything.
Drag and Drop
The Flex 2 docs on how to do drag and drop are pretty good. I
dragEnabled my TileList and it merrily allowed me to drag images all around. However, as soon as I pressed down the mouse, the TileList emitted a
change event. Oops. After a quick read through the documentation, I found that I needed to use
itemClick instead. You see, I want the ImageViewer to pop up when the mouse is clicked; I don’t want it to pop up when I drag an image to the Favorites panel.
In the Favorites panel I also have TileList and on that I placed event handlers for
dragEnter event handler is where you determine if your component is a valid drop target. You get the
dragSource from the DragEvent (in Flex 2 there are many more classes and this one is specific to drag and drop) and look at the
dragFormats supported. If the items being dragged are what your component can handle, then you:
DragManager.acceptDragDrop(event.target)which is different from Flex 1.5.
DragManager.showFeedback(DragManager.LINK). The default is a MOVE which, as it turns out, really removes the item. When I first implemented this in Flex 2, I dragged a thumbnail from the Gallery and dropped it onto the Favorites panel and the item was removed from the Gallery! So I changed this to a LINK operation. I could also have used COPY, but LINK seemed more appropriate.
dragOver event handler is optional. I just set the focus to the Favorites’ TileList.
dragDrop event hanlder is where you add the data to the drop target. Since the data is what goes into the Gallery’s ArrayCollection, it is perfectly suitable for the Favorites TileList since that also uses the Thumbnail for its
listItemRenderer. All I did was add the data from the
dragSource to the Favorites TileList
dataProvider (also an ArrayCollection) and voila – thumbnail appears.
Once a search is successful, I want to remember it in the DataGrid, aka SearchHistory. I already had code to do this from the Flex 1.5 version, so I inserted that into the SearchHistory component and, with an adjustment for the ArrayCollection, things worked.
When using an ArrayCollection, you do use the
addItem method just as you would have with an Array in Flex 1.5. Except, merely using
addItem does not trigger an event to update the TileList. You also have to call
notifyItemUpdate like this:
if( ac == null ) ac = new ArrayCollection(); ac.addItem( searchCriteria ); ac.notifyItemUpdate( searchCriteria );
When the SearchHistory DataGrid is bound to the ArrayCollection
notifyItemUpdate causes the new criteria to be placed into the DataGrid.
This last task was much more complex than I would have liked. In hindsight, there wasn’t much to do, but with 2 bugs in the Flex 2 Alpha 1, I had to find work-arounds.
First, I’ve only made the ImageViewer show the larger size image of the one clicked in either the Gallery or Favorites. None of the controls (information, print, etc.) work yet. Nor does the image information (tags, description, etc.). That will be later.
First issue: TitleWindows are very transparent. Panels are now given an alpha of about .6 I think. TitleWindows seem to be about .2 – nearly invisible. I wound up changing their style to have
headerColors and an alpha of 1.
Second issue: The
click event means ‘click anywhere in the window’, not just the close box. This means that if you have the ImageViewer open and click one of the control buttons (eg, Print), it triggers the
click event for the TitleWindow. I had a listener for this event in the PhotoSearch component which dismisses the window and sets its instance variable to null. So no matter where I clicked, the ImageViewer disappeared.
To circumvent this, I removed the close button and added a specific “Close” button on the ImageViewer’s ControlBar which dispatches a “close” event. Now the only way to dismiss the ImageViewer is to click that button.
Third Issue: Images, on the
complete event have their
height properties set to zero. This means that I could not resize the ImageViewer to see the entire larger image the way I did in Flex 1.5.
As I reported in the last journal, I found a response to that from likn who suggested that I use img.content.width and img.content.height. That worked. So now the ImageViewer reshapes itself properly.
Finally, in keeping with the flow from the Thumbnail, the ImageViewer now builds the URL to the full-size image itself, rather than it being part of the information in the TileList dataProvider ArrayCollection.
This ‘day’ was more intense as I uncovered some problems with the Flex 2 Alpha 1, but found reasonable work-arounds for them. The Flickr PhotoSearch application is about 50% of the way to running as a Flex 2 application. I need to save the search history and favorites list, get the image information/details to display, allow searchs from the image details tags, get searching by Flickr user to work, and more.
Getting drag and drop from the Gallery to the Favorites went really well. Getting the ImageViewer to work was harder due to the
click event issue and then the image sizing issue. And I was disappointed by the Progress Bar, which I would probably have had issues with in Flex 1.5 if I had used a TileList there, too.