Canvas add-on for Vaadin 7

I’m happy to announce that I have released a rewritten version of the Canvas add-on for Vaadin 7. Download it from
the Directory
.

Hi Henri,

I tried to create my own canvas, but it won’t show up. Instead it say “Widgetset does not contain implementation for com.optible.vaadin.eye.VisualEyeComponent. Check its component connector’s @Connect mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions.”

Somewhere in my widget setup there must be a mistake, but I can’t find it. Perhaps you can help.

My component:

public class VisualEyeComponent extends Canvas {...}

VaadinWidgetset.gwt.xml (in /src/main/java/com/optible/vaadin/widgetset/VaadinWidgetset.gwt.xml):

<?xml version="1.0" encoding="UTF-8"?>
<module>
	<inherits name="com.vaadin.DefaultWidgetSet" />
	<inherits name="org.vaadin.hezamu.canvas.CanvasWidgetset" />
	
    <set-property name="user.agent" value="gecko1_8"/>
    
    <!-- <set-configuration-property name="devModeRedirectEnabled" value="true" /> -->

</module>

I am using eclipse 4.2 with the m2e plugin (which I don’t fully trust to be working with the vaadin plugin). In Eclipse I am able to compile the widget set with the vaadin plugin. To deploy to my JBoss 7.1 I normally use the JBoss plugin, but also tried with manually deploying the maven generated ear file.

Basically the project is a maven module with the following pom file:


...
    <artifactId>vaadin</artifactId>
    <packaging>war</packaging>
...
	<properties>
		<vaadin.version>7.0.1</vaadin.version>
		<vaadin.canvas.widget.version>2.0</vaadin.canvas.widget.version>
	</properties>
...

    <dependencies>
...
        <!-- Vaadin -->
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-client</artifactId>
            <version>${vaadin.version}</version>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-client-compiler</artifactId>
            <version>${vaadin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.vaadin.addons</groupId>
            <artifactId>canvas</artifactId>
            <version>${vaadin.canvas.widget.version}</version>
        </dependency>
...
    </dependencies>
...
    <build>
        <defaultGoal>install</defaultGoal>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <id>copy-sass</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/${project.artifactId}/VAADIN/themes/optible</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>${basedir}/src/main/webapp/VAADIN/themes/optible</directory>
                                    <filtering>false</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                        <configuration>
                            <classpathScope>compile</classpathScope>
                            <mainClass>com.vaadin.sass.SassCompiler</mainClass>
                            <arguments>
                                <argument>${basedir}/src/main/webapp/VAADIN/themes/optible/styles.scss</argument>
                                <argument>${project.build.directory}/${project.artifactId}/VAADIN/themes/optible/styles.css</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
       </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.2</version>
                    <configuration>
                        <source>${jdk.version}</source>
                        <target>${jdk.version}</target>
                        <compilerArgument>-proc:none</compilerArgument>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.3</version>
                    <configuration>
                        <packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
                        <archive>
                            <manifest>
                                <addClasspath>true</addClasspath>
                                <classpathPrefix>lib/</classpathPrefix>
                            </manifest>
                            <manifestEntries>
                                <Dependencies>org.apache.xerces,org.jboss.resteasy.resteasy-jackson-provider,org.jboss.resteasy.resteasy-cdi,org.codehaus.jackson.jackson-jaxrs,org.codehaus.jackson.jackson-mapper-asl,org.codehaus.jackson.jackson-core-asl</Dependencies>
                            </manifestEntries>
                        </archive>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    ...
                    
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <profiles>
        <profile>
            <id>compile-widgetset</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.vaadin</groupId>
                        <artifactId>vaadin-maven-plugin</artifactId>
                        <version>${vaadin.version}</version>
                        <executions>
                            <execution>
                                <configuration>
                                    <modules>
                                        <module>com.optible.vaadin.widgetset.VaadinWidgetset</module>
                                    </modules>
                                </configuration>
                                <goals>
                                    <goal>update-widgetset</goal>
                                    <goal>compile</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

Any ideas I should try out? Would be very much appreciated.

Thanks,
Thomas

That sounds awesome!

Would you be able to explain what the practical differences between using your extension versus loading a normal HTML5 canvas as Web content would be? I assume your add-on would have easier interaction with the vaadin UI server, but the HTML5 canvas has more capabilities?

HI Again,

after searching and trying some more things, I can finally answer my own question:
The problem was not the compiling of my widgetset, but the Servlet configuration :-(.

Anyway adding the correct init param “widgetset” did the trick :-).

If you use the cdi addon and have the same problem, this is your code:


    @WebServlet(urlPatterns = "/*", initParams = { @WebInitParam(name = VaadinSession.UI_PARAMETER, value = Props.UI_NAME),
            @WebInitParam(name = Constants.SERVLET_PARAMETER_UI_PROVIDER, value = CdiUIProvider.PROVIDER_NAME),
            @WebInitParam(name = Constants.PARAMETER_WIDGETSET, value = Props.WIDGET_SET_NAME) })
    public static class ApplicationServlet extends VaadinServlet {

        private static final long serialVersionUID = 1L;
    }

@Henri:
Thanks for the great plugin! Exactly what I was looking for.

R.,
Thomas

Hi,
Is there any way to get canvas element position? For example, I draw a circle and when I click to this circle, it must change it’s color or output (x,y) position.

Can this be used to remember the objects drawn on the canvas? That is, when you draw something on it, can whatever was drawn be known (such as the rectangle, will it give me the x,y coordinates as well as the width and height)?

Can objects be selected and moved or resized?

Can the background of the canvas be set to an image that the user will then draw on top of it (no need to modify the underlying image of course)?

I’m looking to allow a scanned document image to be uploaded and then have the user draw rectangles where the various form fields in the scanned document image are. It seems easy to display an image and put input fields and such on top, but the “builder” tool needs to allow the user to set the position/size easily, and this seems very close to allowing it.

Unfortunately the HTML5 canvas is basically just a bitmap and it does not support object or element based drawing.

@David:
You can achieve the background feature by having two overlapping canvases. Position them with position: absolute and draw your background image on the one in back and shapes on the one in front. Scaling may be tricky, though.

Thanks, Henri. It looked like that was the case. Does anybody have any ideas on a simple geometric object drawing tool that we might consider for this purpose? Maybe another open source JS library we can try to integrate with Vaadin?

By the way, I did find Paper.JS that might be a nice base for a Vaadin add-on for those so-inclined.
http://paperjs.org/

Hi, and thanks for an amazing addon!

I need to add some custom graphics (most preferably scalable) to my application. My plan is to draw using gimp/inkscape, export to svg, convert to HTML5 canvas javascript using a tool, and then manually translate the javascript to the java api in this Vaadin addon.

However, I cannot fint the bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) method. Is there an alternative method that I can use, or will this method maybe be available in a later release?

Maybe there are better ways to achieve my goal? I’m just playing around, checking out what’s possible.

Regards
Jon Arne Grødal

I found some unexpected behaviour. Calling setFillStyle using the string constructor, and a six character hex color defintion, such as:

canvas.setFillStyle("ECF1F6");

works fine in Safari, Chrome and Opera (all latest versions), but fails in Firefox and Internet Explorer, where the specified color is substituted with another.

Using setFillStyle with the integer r,g,b constructor works fine in all browsers.

This is a very useful component and thanks for your fine work.
However I’m still getting caching issues. Has this been completely resolved ?
I have a class that draws some stuff. It includes 2 methods. The first one does the caching and the calls the second to do the drawing. The application calls the first method once at the beginning and then only uses the second. This works fine 98% of the time. However a few times it fails to show anything.

public void drawContent() {
this.loadImages(new String {backgroundURL});
this.addListener(new CanvasImageLoadListener() {
public void imagesLoaded() {
drawEvent();
}
});
}

/**
* Do the actual event drawing when background preloading has finished
*/
public void drawEvent () {
this.drawImage2(.... )
} 

Since I couldn’t get this to work reliably (it was even worse on IE and didn’t work at all on android) I replaced drawImage2 with and Embedded below the canvas. This works on all browsers and also on android. Canvas seems to work fine on Android by the way with the exception of drawImage.

At first thanks for this great Addon !!

You load Images with an URL:

canvas.loadImages(new String []{url}

Is there also a way to load Images form a local image?

Is there also a way to load Images form a local image?

Hi,

I just downloaded v2.1 for 7.3.10 and tried to compile from a clean project (no other addons, classes, etc.) – WidgetSet will not compile:

Starting GWT compiler
Compiling module com.ss.cta_editor.widgetset.Cta_editorWidgetset
Validating units:
Ignored 3 units with compilation errors in first pass.
Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.
Resolving com.google.gwt.validation.client.constraints.AbstractDecimalMaxValidator
Found type ‘com.google.gwt.validation.client.constraints.AbstractDecimalMaxValidator’
Found type ‘javax.validation.constraints.DecimalMax’
[WARN]
Detected warnings related to ‘javax.validation.Constraint’. Is validation-.jar on the classpath?
Specify -logLevel DEBUG to see all errors.
[WARN]
Ignoring unresolvable annotation type javax.validation.Constraint
[ERROR]
Unexpected internal compiler error
java.lang.UnsupportedClassVersionError: org/vaadin/hezamu/canvas/Canvas : Unsupported major.minor version 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.google.gwt.dev.javac.CompilationUnitTypeOracleUpdater.resolveAnnotationValue(CompilationUnitTypeOracleUpdater.java:733)
at com.google.gwt.dev.javac.CompilationUnitTypeOracleUpdater.createAnnotation(CompilationUnitTypeOracleUpdater.java:483)
at com.google.gwt.dev.javac.CompilationUnitTypeOracleUpdater.resolveAnnotation(CompilationUnitTypeOracleUpdater.java:641)
at com.google.gwt.dev.javac.CompilationUnitTypeOracleUpdater.resolveAnnotations(CompilationUnitTypeOracleUpdater.java:655)
at com.google.gwt.dev.javac.CompilationUnitTypeOracleUpdater.resolveClass(CompilationUnitTypeOracleUpdater.java:793)
at com.google.gwt.dev.javac.CompilationUnitTypeOracleUpdater.addNewTypesDontIndex(CompilationUnitTypeOracleUpdater.java:397)
at com.google.gwt.dev.javac.CompilationUnitTypeOracleUpdater.addNewTypesDontIndex(CompilationUnitTypeOracleUpdater.java:446)
at com.google.gwt.dev.javac.CompilationUnitTypeOracleUpdater.addNewUnits(CompilationUnitTypeOracleUpdater.java:413)
at com.google.gwt.dev.javac.CompilationState.assimilateUnits(CompilationState.java:191)
at com.google.gwt.dev.javac.CompilationState.(CompilationState.java:99)
at com.google.gwt.dev.javac.CompilationStateBuilder.doBuildFrom(CompilationStateBuilder.java:538)
at com.google.gwt.dev.javac.CompilationStateBuilder.buildFrom(CompilationStateBuilder.java:459)
at com.google.gwt.dev.javac.CompilationStateBuilder.buildFrom(CompilationStateBuilder.java:445)
at com.google.gwt.dev.cfg.ModuleDef.getCompilationState(ModuleDef.java:541)
at com.google.gwt.dev.Precompile.precompile(Precompile.java:241)
at com.google.gwt.dev.Precompile.precompile(Precompile.java:223)
at com.google.gwt.dev.Precompile.precompile(Precompile.java:139)
at com.google.gwt.dev.Compiler.run(Compiler.java:169)
at com.google.gwt.dev.Compiler.run(Compiler.java:132)
at com.google.gwt.dev.Compiler$1.run(Compiler.java:100)
at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:55)
at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:50)
at com.google.gwt.dev.Compiler.main(Compiler.java:107)
at com.vaadin.tools.WidgetsetCompiler$1.run(WidgetsetCompiler.java:80)
at java.lang.Thread.run(Unknown Source)
Widgetset compilation failed

It was a Java8 issue. Jar was Java 8, I am using 7.

So I copied the files to my project and tried to compiled Widgetset – worked.

But
it seems to have its own. See attached error message image.

Tried several things…removing, commenting out, etc. – no joy.
Note in the above thread about this … but above my head in solving.

Suggestions?

Thansk,
Greg

18221.png

Got it!

Had to point the UI to the compiled widgetset.

That widgetset has to have an <inherit…> of the Canvas widgetset.

All very logic, but in NO way obvious. Yes, the s/w engineering way. :wink:

Is there an easy way to draw an image that is loaded as a Resource?