Overlays - Yet another new fancy add-on component

If you have ever wanted to add an image or a text overlay on any Vaadin component, the Overlays add-on is for you.

With ImageOverlay you can put a small (or large) images on top of other components. Like a “New”-icon to highlight a recently added feature or item:

ImageOverlay newLogo = new ImageOverlay(codePanel, new ClassResource(this
        .getClass(), "images/newLogo.png", this));
newLogo.setComponentAnchor(Alignment.TOP_RIGHT);
newLogo.setOverlayAnchor(Alignment.MIDDLE_CENTER);
mainWindow.addComponent(newLogo);

Or if you want to simply add a “No items found” text in the middle of an empty Table, simply use TextOverlay:

TextOverlay notFoundOverlay = new TextOverlay(table, "<i>[No entries found]
</i>");
notFoundOverlay.setContentMode(TextOverlay.CONTENT_RAW);
notFoundOverlay.setComponentAnchor(Alignment.MIDDLE_CENTER);
notFoundOverlay.setOverlayAnchor(Alignment.MIDDLE_CENTER);
mainWindow.addComponent(notFoundOverlay);

All overlays can bound and anchored to virtually any other Vaadin component. Also the anchor point in the overlay can be specified using Alignment constants. This allows quick and easy positioning of overlay on Buttons, TextFields, Selects, etc. Furthermore, the position can be fine-tuned using x and y offsets. Overlays can also be anchored to each other as well as stacked.

This is still an experimental component and some browsers may misbehave. I also request for comments for the overlay API, method naming and features.


Try the demo here!


Source code is here
(Apache License 2.0)

For your convenience I attached the 6.2 compatible add-on jar file.
11204.jar (103 KB)

Hello,

cool component.
But unfortunaly it does not work under vaadin 6.3.0.

Compiling the widgetset throws this error:

Loading inherited module 'org.vaadin.overlay.OverlayWidgetset'
   Loading inherited module 'org.vaadin.codelabel.CodelabelWidgetset'
      [ERROR]
 Unable to find 'org/vaadin/codelabel/CodelabelWidgetset.gwt.xml' on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?
   [ERROR]
 Line 24: Unexpected exception while processing element 'inherits'
com.google.gwt.core.ext.UnableToCompleteException: (see previous log entries)
        at com.google.gwt.dev.cfg.ModuleDefLoader.nestedLoad(ModuleDefLoader.java:239)
        at com.google.gwt.dev.cfg.ModuleDefSchema$BodySchema.__inherits_begin(ModuleDefSchema.java:354)
        at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.google.gwt.dev.util.xml.HandlerMethod.invokeBegin(HandlerMethod.java:223)
        at com.google.gwt.dev.util.xml.ReflectiveParser$Impl.startElement(ReflectiveParser.java:270)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
        at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:179)
        at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.emptyElement(XMLDTDValidator.java:788)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1343)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2755)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
        at com.google.gwt.dev.util.xml.ReflectiveParser$Impl.parse(ReflectiveParser.java:327)
        at com.google.gwt.dev.util.xml.ReflectiveParser$Impl.access$100(ReflectiveParser.java:48)
        at com.google.gwt.dev.util.xml.ReflectiveParser.parse(ReflectiveParser.java:398)
        at com.google.gwt.dev.cfg.ModuleDefLoader.nestedLoad(ModuleDefLoader.java:257)
        at com.google.gwt.dev.cfg.ModuleDefSchema$BodySchema.__inherits_begin(ModuleDefSchema.java:354)
        at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.google.gwt.dev.util.xml.HandlerMethod.invokeBegin(HandlerMethod.java:223)
        at com.google.gwt.dev.util.xml.ReflectiveParser$Impl.startElement(ReflectiveParser.java:270)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
        at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:179)
        at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.emptyElement(XMLDTDValidator.java:788)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1343)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2755)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
        at com.google.gwt.dev.util.xml.ReflectiveParser$Impl.parse(ReflectiveParser.java:327)
        at com.google.gwt.dev.util.xml.ReflectiveParser$Impl.access$100(ReflectiveParser.java:48)
        at com.google.gwt.dev.util.xml.ReflectiveParser.parse(ReflectiveParser.java:398)
        at com.google.gwt.dev.cfg.ModuleDefLoader.nestedLoad(ModuleDefLoader.java:257)
        at com.google.gwt.dev.cfg.ModuleDefLoader$1.load(ModuleDefLoader.java:169)
        at com.google.gwt.dev.cfg.ModuleDefLoader.doLoadModule(ModuleDefLoader.java:283)
        at com.google.gwt.dev.cfg.ModuleDefLoader.loadFromClassPath(ModuleDefLoader.java:141)
        at com.google.gwt.dev.Compiler.run(Compiler.java:184)
        at com.google.gwt.dev.Compiler$1.run(Compiler.java:152)
        at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:87)
        at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:81)
        at com.google.gwt.dev.Compiler.main(Compiler.java:159)
   [ERROR]
 Failure while parsing XML

André

Wow, that’s really fresh UI addon !
IMO seems to be a very useful addon !

Haven’t tested yet with 6.3, but the exception you encountered is because the
CodeLabel add-on
is missing from your project.

I’m sorry about this unnecessary dependency. Overlays classes does not actually depend on CodeLabel. It is just because I used it in the
Overlays Demo Application
to highlight the generated sample code, but the add-on packaging mechanism exports this dependency. :frowning:

I’ll split the demo to separate project and publish a new version of Overlays to get rid of this.

Would be nice.

Thanks.

Ok, I just submitted a version 0.9.4 of the
Overlays
to the Directory. Along with the dependency issue described above this fixes a FF 3.6 incompatibility I encountered. Also compiled and tested with the latest Vaadin 6.3.1.


Download Overlays Add-on from Vaadin Directory

That was fast.

Thanks.

Hmmm…

as soon as I add it to my project and recompile the widgetset, my initial screen gets blank (height: 0px)
I do not even need to place the overlay component on the screen, just the presence of the jar file causes this strange behaviour…

Anyone seen this problem too ?

As the project is very large, I not had yet time to try to find out if there is a conflict with other components.

André

There is this one thing…

Overflow settings in the application window are changed (using CSS) to allow positioning of the overlays to work:


.v-generated-body {
	overflow: auto;
}

.v-generated-body .v-app {
	height: auto;
}

Try remove these, but beware some problems while scrolling. These might have some side effects depending the application theme is otherwise designed and if the application is embedded to a html page for example.

I downloaded the latest version of the add-on (0.9.4) and it gives me an error in the client application:

Widgetset does not contain implementation for org.vaadin.overlay.CustomOverlay. Check its @ClientWidget mapping, widgetsets GWT module descrioption file and re-compile your widgetset. Unrendered UIDL:

org.vaadin.overlay.CustomOverlay(NO CLIENT IMPLEMENTATION FOUND) id=PID72 comp=PID73 align=6 overlayAlign=48 x=0 y=0

This is my code to create the overlay, which I’m trying to place on a tab sheet


Resource aLogo = new ThemeResource("images/customer-logo.gif");

ImageOverlay aLogoOverlay = new ImageOverlay();
aLogoOverlay.setComponentAnchor(Alignment.TOP_RIGHT);
aLogoOverlay.setOverlayAnchor(Alignment.MIDDLE_CENTER);
aLogoOverlay.setXOffset(0);
aLogoOverlay.setYOffset(0);

aLogoOverlay.setImage(aLogo);

// then later on to add the overlay...

Panel p = new Panel();

aLogoOverlay.setComponent(mTabSheet);
					
p.addComponent(aLogoOverlay);
p.addComponent(mTabSheet);

// container is a panel which is put into the bottom half of a split pane in the main window, fwiw.
setContent(p);

What am I missing?

Ah, I was missing the inherit of the widget set. Now the overlay kind of works. It’s on screen, but it’s the only thing on screen and it covers the entire window so the only thing visible is the overlay, not quite what I was going for.

Yes, the theme inheritance is one gotcha. Glad you got over it :slight_smile:

Otherwise, have you tried to set the size (width and height in pixels) for the overlay? If it covers the entire view Id say the image is too big or it tries to use 100% width based on the page size.

No, I haven’t tried that yet, but it’s not clear to me that is the issue. What I’ve done is removed all the overlay code, there’s not a single reference to it anywhere in the source, thought it’s still in the class path.

If I inherit the module, the entire application is not visible. If I comment out inheriting the module, the application is visible again.

Is the overlays module overriding some defaults?

I think it maybe is the CSS provided with overlays? If I copy the CSS definitions from overlay into my application, I can get the same behavior, the application does not show up.

Of course, I un-jarred overlays, removed the CSS, re-jarred and tried that and still no luck, same behavior of the entire application is not visible. Maybe something is hard-coded?

Any ideas?

Everything should be in the CSS. I think that you should not even have to extract anything to change that, but just create a new theme where you redefine the CSS rules.

But yes, you are right. The provided CSS changes how the application overflow should be handled (.v-app CSS class) and this is because otherwise scrolling mixes up the overlay position calculations. This should not have any nasty side effects unless you are embedding the application to a HTML page or something similar.

I don’t remember the exact changes by heart, but you could try to reverse them back in you application theme. Another option would be to specify explicit size for the v-app class.

I opened the DOM with Chrome and I started clicking through and notice, by inheriting overlays in my widgetset, every single component in my entire application has a height of 0px. If I remove the inherits assertion, sizing is correct and the app is visible.

I just updated from Vaadin 6.2.3 to 6.3.2 to use this component, so maybe it’s just something I’m missing that changed between versions?

Looking at your code, I don’t see how this could happen (height for everything set to 0), and explicitly setting the height for .v-generated-body and .v-app don’t seem to affect things.

In fact, it looks like the only way to get the application to draw correctly is to explicitly set a height for the .v-view class:

.v-view {
height:800px;
}

100% and auto don’t work here, only a specific size…

But I don’t really want to hardcode a size for my application, I just want it to be the size of the window.

Ideas?

We too have this problem.

For the moment we have postponed usage of the component until we have some more spare time to look at it.

André

I did test briefly with the 6.3.1, but it seems I have to I’ll test more thoroughly with latest 6.3. I’ll let you know.

Ok, I need some more specific information and/or a test case. I tested the Overlays with Vaadin 6.3.2 and did not encounter any unexpected behavior. The current demo is running the Overlays with Vaadin 6.3.2: http://sami.virtuallypreinstalled.com/overlays/

I also uploaded a new version of Overlays. 0.9.6 with a click support:

overlay.setClickListener(new OverlayClickListener() {
      public void overlayClicked(CustomClickableOverlay overlay) {
            mainWindow.showNotification("Overlay Clicked!");
      }
});

Download here:
http://vaadin.com/directory#!addon/68

The new version still does not work for me. If I don’t explicitly set the height of my application in the css, which is bad practice, the entire application is invisible by simply including overlays in the application (I don’t even need to reference it in my code).

I’m able to get the application to display on screen by explicitly setting a height, but the overlay is displayed in at top left corner of the entire application, and not the top right corner of a specific sub-component and the sub-component i was trying to put the overlay on displays at it’s minimum width and height rather than the 100%-100% it’s set at in the CSS.

Do you (or anyone) have any examples of using overlays with a non-toy application? The online demo source is not in the SVN repo last I checked, but even that is way more simplistic than any normal application layout.

It’s hard for me to distill my application down to a test case, there’s ten’s of thousands of lines of code here, but if I could see a more realistic usage example, I might be able to see what the diff is between that I’m doing and what I should be doing.