I haven't sorted out in my mind the best approach for a few of the details, 
in particular making it reusable, but this works.  Consider it more of a 
"proof of concept".

You'd need to create red.png in the war directory, or could try out a data 
url (which per my tests works with this).

For a bundle with more images, the asynchronicity gets to be a bigger 
issue, since you'd need to have something like a "master" callback once all 
of the individual image callbacks have completed.  Also, there's no 
facility for sprites, although I think it could be implemented.


public class DynamicResourcesDemo implements EntryPoint {
    
    private DynamicMenuBarResources resources;
    private MenuBar bar;

    public void onModuleLoad() {
        
        MenuBar.Resources defaultResources = 
GWT.create(MenuBar.Resources.class);
        MyImageResource imgres = new 
MyImageResource(defaultResources.menuBarSubMenuIcon());
        resources = new DynamicMenuBarResources(imgres);
        
        imgres.load("red.png", new Callback<Void, Throwable>() {
            @Override
            public void onSuccess(Void result) {
                showUi();
            }
            
            @Override
            public void onFailure(Throwable reason) {
                Window.alert("Error");
            }
        });
    }
    
    private void showUi() {
        MenuBar fileMenu = new MenuBar(true);
        fileMenu.addItem("Open", new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                Window.alert("Open File");
            }
        });
        fileMenu.addItem("Exit", new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                Window.alert("So long!");
            }
        });
        MenuBar actionsMenu = new MenuBar(true, resources);
        actionsMenu.addItem("File", fileMenu);
        bar = new MenuBar();
        bar.addItem("Actions", actionsMenu);
        
        RootPanel.get().add(bar);
    }
}

//-------------------------------------------------------------

public class DynamicMenuBarResources implements Resources {
    
    private static Resources base = GWT.create(Resources.class);
    private ImageResource menuBarSubmenuIconResource;

    public DynamicMenuBarResources() {
    }

    public DynamicMenuBarResources(ImageResource 
menuBarSubmenuIconResource) {
        this.menuBarSubmenuIconResource = menuBarSubmenuIconResource;
    }

    @Override
    @ImageOptions(flipRtl = true)
    public ImageResource menuBarSubMenuIcon() {
        if (menuBarSubmenuIconResource != null) {
            return menuBarSubmenuIconResource;
        } else {
            return base.menuBarSubMenuIcon();
        }
    }

}

//----------------------------------------------------

public class MyImageResource implements ImageResource {
    
    private Image image;
    private ImageResource defaultResource;
    private boolean imageValid = false;
    
    public MyImageResource(ImageResource defaultResource) {
        image = new Image();
        this.defaultResource = defaultResource;
    }

    public void load(String url, final Callback<Void, Throwable> callback) {
        image.setUrl(url);
        final Panel pnl = new SimplePanel();
        pnl.add(image);
        Style pnlStyle = pnl.getElement().getStyle();
        pnlStyle.setVisibility(Visibility.HIDDEN);
        pnlStyle.setPosition(Position.ABSOLUTE);
        image.addLoadHandler(new LoadHandler() {
            @Override
            public void onLoad(LoadEvent event) {
                RootPanel.get().remove(pnl);
                imageValid = true;
                if (callback != null) callback.onSuccess(null);
            }
        });
        image.addErrorHandler(new ErrorHandler() {
            @Override
            public void onError(ErrorEvent event) {
                RootPanel.get().remove(pnl);
                // this lets the resource fall back to the default
                if (callback != null) callback.onSuccess(null);
                // this would instead invoke the error handling for the 
callback
                //if (callback != null) callback.onFailure(new 
Exception("Image Resource Load Error"));
            }
        });
        RootPanel.get().add(pnl);
    }

    @Override
    public String getName() {
        return imageValid ? "" : defaultResource.getName();  // ???
    }

    @Override
    public int getHeight() {
        return imageValid ? image.getHeight() : defaultResource.getHeight();
    }

    @Override
    public int getLeft() {
        return imageValid ? 0 : defaultResource.getLeft();
    }

    @Override
    public SafeUri getSafeUri() {
        return imageValid ? UriUtils.fromSafeConstant(image.getUrl()) : 
defaultResource.getSafeUri();
    }

    @Override
    public int getTop() {
        return imageValid ? 0 : defaultResource.getTop();
    }

    @Override
    @Deprecated
    public String getURL() {
        return imageValid ? image.getUrl() : defaultResource.getURL();
    }

    @Override
    public int getWidth() {
        return imageValid ? image.getWidth() : defaultResource.getWidth();
    }

    @Override
    public boolean isAnimated() {
        return imageValid ? false : defaultResource.isAnimated();  // ???
    }

}


On Saturday, August 17, 2013 12:30:11 PM UTC-4, df wrote:
>
> Could you give some code?
> Thanks
>
> W dniu czwartek, 15 sierpnia 2013 01:05:30 UTC+2 użytkownik Steve C 
> napisał:
>>
>> Thanks for asking that question - it led me to a solution to a problem 
>> that I've had, which is "skinning" an app using different versions of 
>> resources loaded asynchronously from the war directory as opposed to coded 
>> into a ClientBundle.
>>
>> I created a client bundle extending SimplePager.Resources, with sources 
>> that reference dummy placeholder images in my source tree, then created a 
>> separate class implementing that interface.  In the constructor I populate 
>> it from the GWT.created bundle (since some of the resources aren't dynamic, 
>> and I can just delegate through to them) but then load my dynamic images 
>> into Image widgets. Those, in turn, are each given to an implementation of 
>> ImageResource that holds an Image widget, and obtains the width, height, 
>> url, etc. from it (wasn't sure what the heck to do with getName, or how to 
>> implement isAnimated). Those are the return values from the associated 
>> methods in my resource object.  And then I give that to the pager 
>> constructor.
>>
>> The asychronicity turned out to be a bear, since I'm using a LoadHandler 
>> for each image to know when the size values will be available, and that 
>> won't do anything unless I actually add the Image to the document, so I had 
>> to create a hidden div to put them into. I haven't yet tested if that's 
>> necessary with a data: url. And a lot of layout tasks had to be pushed off 
>> into a callback.
>>
>> The concept works, but I suspect that unless I make all versions of a 
>> particular image the same size, I can't use any CssResource tricks based on 
>> the image. That's probably not a big deal - since the variations generally 
>> would all be the same size.  Also, I don't think that there's any existing 
>> Resource class in the API with CSS resources that depend on the images, so 
>> it would only be an issue with custom resource classes.
>>
>> On Wednesday, August 14, 2013 3:42:34 AM UTC-4, df wrote:
>>>
>>> Hello. Is There any way to create ImageResource dynamically? For example 
>>> : I get images from WebService in base64 format and I don't have 
>>> opportunity to have all images on the server at compile time. Can i cast 
>>> Images to ImageResource? Or is there any other solution?
>>> Thanks for help.
>>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-web-toolkit+unsubscr...@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to