0

I've extended IconItemRenderer to create a custom item renderer needed for a project I am working on. The renderer works fine right now, except I cannot figure out how to add more images beyond the icon and decorator. I need to add three additional images and cannot figure out how.

What I have been trying (the renderer is entirely written in AS3):

override protected function createChildren():void {
    super.createChildren();
    this.downloadIcon = new BitmapImage();
    this.downloadIcon.source = "assets/images/download-160.png";
    var down:DisplayObject = this.downloadIcon.createDisplayObject();
    this.addChild( down );
}

As far as I can tell, that should work. If I load that source as the iconDisplay source, it loads just fine so it isn't the source. It also does not matter what source I use (or even local vs external). I have also tried using code from the IconItemRenderer source to no avail:

private function assignDisplayObject(bitmapImage:BitmapImage):void
{
    if (bitmapImage)
    {
        // try using this display object first
        if (bitmapImage.setSharedDisplayObject(this))
        {
            bitmapImage.displayObjectSharingMode = DisplayObjectSharingMode.USES_SHARED_OBJECT;
        }
        else
        {
            // if we can't use this as the display object, then let's see if 
            // the icon already has and owns a display object
            var ownsDisplayObject:Boolean = (bitmapImage.displayObjectSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT);

            // If the element doesn't have a DisplayObject or it doesn't own
            // the DisplayObject it currently has, then create a new one
            var displayObject:DisplayObject = bitmapImage.displayObject;
            if (!ownsDisplayObject || !displayObject)
                displayObject = bitmapImage.createDisplayObject();

            // Add the display object as a child
            // Check displayObject for null, some graphic elements
            // may choose not to create a DisplayObject during this pass.
            if (displayObject)
                addChild(displayObject);

            bitmapImage.displayObjectSharingMode = DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT;
        }
    }        
}

Nothing displays using either method. Could someone explain what I am doing wrong with this?

Using Flex 4.10 and AIR 3.8 if that helps at all.

EDIT: As requested by Reboog, here is the full item renderer minus imports

public class VideoItemRenderer extends IconItemRenderer
{
private static const OUTER_PADDING:uint = 15;
private static const INNER_PADDING:uint = 10;

private var description:StyleableTextField;
private var progressBar:ProgressBar;
private var downloadContainer:Group;
private var deleteIcon:VideoDeleteIcon;
private var downloadIcon:Image;

public function VideoItemRenderer()
{
    super();

    this.addEventListener( FlexEvent.DATA_CHANGE, this.dataChangeHandler );
    this.minHeight = 106;
    this.iconFunction = this.iconSelectFunction;
    this.iconHeight = 76;
    this.iconWidth = 107;
}

private function iconSelectFunction( item:Object ):Object {
    return "assets/images/background-160.png";
}

override protected function createChildren():void {
    super.createChildren();

    this.labelDisplay.wordWrap = true;
    this.labelDisplay.multiline = true;

    this.description = StyleableTextField(createInFontContext(StyleableTextField));
    this.description.styleName = this;
    this.description.editable = false;
    this.description.selectable = false;
    this.description.multiline = true;
    this.description.wordWrap = true;
    this.description.setStyle( "fontFamily", "josefin" );
    this.description.setStyle( "fontWeight", "bold" );
    this.description.text = "Vestibulum id ligula porta felis euismod semper. Cras mattis consectetur purus sit amet.";
    this.addChild( this.description );

    this.deleteIcon = new VideoDeleteIcon();
    this.deleteIcon.addEventListener( MouseEvent.CLICK, this.deleteClickHandler );
    this.addChild( this.deleteIcon );

    this.downloadContainer = new Group();
    this.addChild( this.downloadContainer );

    this.progressBar = new ProgressBar();
    this.downloadContainer.addChild( this.progressBar );

    this.downloadIcon = new Image();
    this.downloadIcon.source = "assets/images/download-160.png";
    this.downloadContainer.addChild( downloadIcon );
}

override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void {
    unscaledWidth = Math.min( this.owner.width, unscaledWidth );

    graphics.beginFill( 0xffffff, .1 );
    graphics.drawRect( 0, 0, unscaledWidth, unscaledHeight );
    graphics.endFill();
    opaqueBackground = null;
}

override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void {
    unscaledWidth = Math.min( this.owner.width, unscaledWidth );
    super.layoutContents( unscaledWidth, unscaledHeight );

    if ( this.iconDisplay ) {
        this.setElementSize( this.iconDisplay, 107, 76 );
        this.setElementPosition( this.iconDisplay, OUTER_PADDING, OUTER_PADDING );

        this.setElementPosition( this.labelDisplay, this.iconDisplay.x + this.getElementPreferredWidth( this.iconDisplay ) + INNER_PADDING, OUTER_PADDING );
        this.setElementPosition( this.description, this.iconDisplay.x + this.getElementPreferredWidth( this.iconDisplay ) + INNER_PADDING, this.labelDisplay.y + this.getElementPreferredHeight( this.labelDisplay ) + INNER_PADDING );
    }
    else {
        this.setElementPosition( this.labelDisplay, OUTER_PADDING, OUTER_PADDING );
        this.setElementPosition( this.description, OUTER_PADDING, this.labelDisplay.y + this.getElementPreferredHeight( this.labelDisplay ) + INNER_PADDING );
    }
    this.setElementSize( this.labelDisplay, unscaledWidth - this.labelDisplay.x - OUTER_PADDING, this.getElementPreferredHeight( this.labelDisplay ) );
    this.setElementSize( this.description, unscaledWidth - this.description.x - OUTER_PADDING, this.getElementPreferredHeight( this.description ) );
    this.setElementPosition( this.deleteIcon, unscaledWidth - this.getElementPreferredWidth( this.deleteIcon ), 0 );

    var descriptionHeight:Number = this.description.y + this.getElementPreferredHeight( this.description );
    var iconHeight:Number = this.iconDisplay ? this.iconDisplay.y + this.getElementPreferredHeight( this.iconDisplay ) : 0;

    //this.setElementSize( this.progressBar, this.description.width, 5 );
    this.progressBar.width = this.description.width;
    this.setElementPosition( this.downloadContainer, 0,Math.max( descriptionHeight, iconHeight ) + OUTER_PADDING );
    this.setElementPosition( this.progressBar, this.description.x, ( this.getElementPreferredHeight( this.downloadContainer ) - this.getElementPreferredHeight( this.progressBar ) ) / 2 );

    var downloadHeight:Number = this.getElementPreferredHeight( this.downloadContainer ) + this.downloadContainer.y;
    this.height = downloadHeight + OUTER_PADDING;
}

private function dataChangeHandler( e:FlexEvent ):void {
    if ( this.data ) {
        this.label = this.data.label.toUpperCase();
    }
}
}
Josh
  • 8,079
  • 3
  • 24
  • 49
  • Why not just use an Image instead of a BitMapImage? If I had to guess you are using createDisplayObject() before the BitMapImage instance has been rendered; therefore nothing shows up. – JeffryHouser Aug 27 '13 at 18:05
  • @Reboog711 I was using `BitmapImage` because I had previously tried using `Image` and nothing displayed. I dug through `IconItemRenderer`'s source to figure out how the `iconDisplay` was rendered and tried to mimic that. I just tried Image again and it still does not display. Your point about the image not being rendered yet is probably accurate, though that doesn't explain why it fails in Image as well. – Josh Aug 27 '13 at 18:13
  • Next guess is that the Image is being displayed under something else; essentially completely hidden. But, I don't think you've provided enough information for me to know for sure. – JeffryHouser Aug 27 '13 at 18:16
  • I haven't given enough info for that, but it definitely is not. It's the last thing added to the renderer and even on a renderer with no content whatsoever doesn't display the image. (just using `addChild( Image )` now) – Josh Aug 27 '13 at 18:44
  • How about you share your full renderer? – JeffryHouser Aug 27 '13 at 19:04
  • @Reboog711 I just added it. The ProgressBar and VideoDeleteIcon are just drawn classes using the `Graphics` class. I have not added in support for multiple DPI ranges or the other images yet (only the main icon and the downloadIcon I am currently trying to get to display) – Josh Aug 27 '13 at 19:16
  • I should have seen this before, but since you're using iconItemRenderer; are you building a mobile app? Your source is a relative URL. Do they work in a desktop situation? Perhaps change it to an absolute URL using either the 'file' syntax or http to a remote server. – JeffryHouser Aug 27 '13 at 19:21
  • @Reboog711 It is a mobile app, yes. Switching to a remote server source does not change anything (I tried loading my avatar from SO, which worked in the iconDisplay but not in my downloadIcon). (I appreciate your help, by the way. Thank you for taking the time) – Josh Aug 27 '13 at 19:25
  • @Reboog711 I managed to get it to display finally... by creating a separate component extending Group that houses the Image. I really have no idea why it required going that far. If I find anything more, I'll be sure to post it – Josh Aug 27 '13 at 19:33
  • @Reboog711 I determined the actual source of the problem. See the answer I just posted – Josh Aug 27 '13 at 19:42

1 Answers1

0

Ok, so I managed to figure out what was going on.

Originally, I tried adding the image to the downloadContainer which was a Sprite (honest mistake on my part; just finished an AS3 project last week). It appears that using downloadContainer.addChild(Image) does not appear to be possible, which is why IconItemRenderer uses BitmapImage#createDisplayObject() and adds the created DisplayObject.

I switched the container to a Group, used addElement, and made ProgressBar extend UIComponent instead of Sprite and everything worked as I believed it should have originally.

So use this:

var container:Group = new Group();
addChild( container );
var image:Image = new Image();
image.source = "blah.png";
container.addElement( image );

That will successfully add the image.

Josh
  • 8,079
  • 3
  • 24
  • 49