Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
component reference in shared state
Hello,
I'm trying to wrap gwt-graphics add-on in a vaadin component but I miss some Vaadin basics.
Here is some simplified code :
server side code :
public class SvgTestUI extends UI {
@Override
protected void init(VaadinRequest request) {
VerticalLayout layout = new VerticalLayout();
setContent(layout);
layout.addComponent(new Label("HelloWorld"));
SvgDrawingArea svgDrawingArea = new SvgDrawingArea(800,500);
SvgRectangle svgRectangle = new SvgRectangle(50,50, 400, 400);
svgDrawingArea.addRectangle(svgRectangle);
layout.addComponent(svgDrawingArea);
}
}
public class SvgDrawingArea extends AbstractComponent {
@Override public SvgDrawingAreaState getState() { return (SvgDrawingAreaState) super.getState(); }
public SvgDrawingArea(int width, int height) {
super.setWidth(width, Unit.PIXELS);
super.setHeight(height, Unit.PIXELS);
}
public void addRectangle(SvgRectangle rectangle) {
getState().rectangle = rectangle;
}
}
public class SvgRectangle extends AbstractComponent {
@Override public SvgRectangleState getState() { return (SvgRectangleState) super.getState(); }
public SvgRectangle(int x, int y, int width, int height) {
getState().x = x;
getState().y = y;
super.setWidth(width, Unit.PIXELS);
super.setHeight(height, Unit.PIXELS);
}
}
shared states
public class SvgDrawingAreaState extends AbstractComponentState {
public Connector rectangle;
}
public class SvgRectangleState extends AbstractComponentState {
public int x, y;
}
connectors
@Connect(SvgDrawingArea.class)
public class SvgDrawingAreaConnector extends AbstractComponentConnector {
@Override protected DrawingArea createWidget() {
DrawingArea drawingArea = new DrawingArea(0,0);
return drawingArea;
}
@Override public DrawingArea getWidget() {
return (DrawingArea) super.getWidget();
}
@Override public SvgDrawingAreaState getState() {
return (SvgDrawingAreaState) super.getState();
}
@Override public void onStateChanged(StateChangeEvent stateChangeEvent) {
Util.updateStateSize(getState());
super.onStateChanged(stateChangeEvent);
SvgDrawingAreaState state = getState();
getWidget().setWidth(getState().width);
getWidget().setHeight(getState().height);
if (state.rectangle != null) {
SvgRectangleConnector svgRectangleConnector = (SvgRectangleConnector)state.rectangle;
Rectangle rectangle = svgRectangleConnector.getWidget();
getWidget().add(rectangle);
}
}
}
The client-side rectangle reference on the SvgDrawingAreaState state is always null.
In the Vaadin doc I see this statement : "You should also notice that the connector you are sending still needs to be present in the connector hierarchy, otherwise the client-side will always see a null reference.". But I don't undestand it.
Where am I wrong ?
Thanks!
Franck
Hi Franck,
The statement means that there cannot be "free-floating" connectors in a Vaadin UI - every connector except the UI itself has to be some other connector's child - that is, A is B's child if A.getParent() == B and B.iterator() yields A when iterated over. Basically this means that your SvgDrawingArea needs to extend AbstractComponentContainer, or perhaps preferably, extend CustomComponent and wrap such an AbstractComponentContainer implementation to shield the container from accidentally adding arbitrary components to it.
Hi Johanes,
Thanks for your advice. I've been digging since yesterday and came to a variation.
My code is now functional.
For people who face the same interrogation and who felt on my post here are my updates :
SvgDrawingArea implements HasComponents
public class SvgDrawingArea extends AbstractComponent implements HasComponents {
.......
public void addShape(SvgShape shape) {
getState().shapes.add(shape);
shape.setParent(this);
}
@Override public Iterator<Component> iterator() {
List<Component> l = new ArrayList<Component>();
for (Connector c : getState(false).shapes) {
l.add((Component) c);
}
return l.iterator();
}
SvgDrawingAreaConnector extends AbstractComponentContainerConnector
@Connect(SvgDrawingArea.class) public class SvgDrawingAreaConnector extends AbstractComponentContainerConnector {
.......
@Override
public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent connectorHierarchyChangeEvent) { }
@Override
public void updateCaption(ComponentConnector connector) { }
Franck
Yeah, sorry, I totally forgot that in this case it's probably way easiest just to implement HasComponents directly. Nicely figured out!