ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 01.01.2026

Просмотров: 2622

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Integrating with the Server-Side

You can pass the most common standard Java types, such as primitive and boxed primitive types, String, and arrays and some collections (List, Set, and Map) of the supported types. Also the Vaadin Connector and some special internal types can be passed.

An RPC method must return void - the widget set compiler should complain if it doesn't.

Making a Call

Before making a call, you need to instantiate the server RPC object with RpcProxy.create(). After that, you can make calls through the server RPC interface that you defined, for example as follows:

@Connect(MyComponent.class) public class MyComponentConnector

extends AbstractComponentConnector {

MyComponentServerRpc rpc = RpcProxy

.create(MyComponentServerRpc.class, this);

public MyComponentConnector() { getWidget().addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) { final MouseEventDetails mouseDetails =

MouseEventDetailsBuilder

.buildMouseEventDetails(

event.getNativeEvent(), getWidget().getElement());

// Make the call rpc.clicked(mouseDetails);

}

});

}

}

Handling a Call

RPC calls are handled in a server-side implementation of the server RPC interface. The call and its parameters are serialized and passed to the server in an RPC request transparently.

public class MyComponent extends AbstractComponent { private MyComponentServerRpc rpc =

new MyComponentServerRpc() { private int clickCount = 0;

public void clicked(MouseEventDetails mouseDetails) { Notification.show("Click from the client!");

}

};

public MyComponent() {

...

registerRpc(rpc);

}

}

16.7. Component and UI Extensions

Adding features to existing components by extending them by inheritance creates a problem when you want to combine such features. For example, one add-on could add spell-check to a TextField, while another could add client-side validation. Combining such add-on features would be difficult if not impossible. You might also want to add a feature to several or even to all com-

Component and UI Extensions

369


Integrating with the Server-Side

ponents, but extending all of them by inheritance is not really an option. Vaadin includes a component plug-in mechanism for these purposes. Such plug-ins are simply called extensions.

Also a UI can be extended in a similar fashion. In fact, some Vaadin features such as the JavaScript execution are UI extensions.

Implementing an extension requires defining a server-side extension class and a client-side connector. An extension can have a shared state with the connector and use RPC, just like a component could.

16.7.1. Server-Side Extension API

The server-side API for an extension consists of class that extends (in the Java sense) the AbstractExtension class. It typically has an extend() method, a constructor, or a static helper method that takes the extended component or UI as a parameter and passes it to super.extend().

For example, let us have a trivial example with an extension that takes no special parameters:

public class CapsLockWarning extends AbstractExtension { public void extend(PasswordField field) {

super.extend(field);

}

}

The extension can then be added to a component as follows:

PasswordField password = new PasswordField("Give it"); new CapsLockWarning().extend(password); layout.addComponent(password);

Adding a feature in such a "reverse" way is a bit unusual in the Vaadin API, but allows type safety for extensions, as the method can limit the target type to which the extension can be applied, and whether it is a regular component or a UI.

16.7.2. Extension Connectors

An extension does not have a corresponding widget on the client-side, but only an extension connector that extends the AbstractExtensionConnector class.The server-side extension class is specified with a @Connect annotation, just like in component connectors.

An extension connector needs to implement the extend() method, which allows hooking to the extended component. The normal extension mechanism is to modify the extended component as needed and add event handlers to it to handle user interaction. An extension connector can share a state with the server-side extension as well as make RPC calls, just like with components.

In the following example, we implement a "Caps Lock warning" extension. It listens for changes in Caps Lock state and displays a floating warning element over the extended component if the Caps Lock is on.

@Connect(CapsLockWarning.class) public class CapsLockWarningConnector

extends AbstractExtensionConnector {

@Override

protected void extend(ServerConnector target) { // Get the extended widget

final Widget passwordWidget = ((ComponentConnector) target).getWidget();

370

Server-Side Extension API



Integrating with the Server-Side

//Preparations for the added feature final VOverlay warning = new VOverlay();

warning.add(new HTML("Caps Lock is enabled!"));

//Add an event handler

pw.addDomHandler(new KeyPressHandler() {

public void onKeyPress(KeyPressEvent event) { if (isEnabled() && isCapsLockOn(event)) {

warning.showRelativeTo(passwordWidget); } else {

warning.hide();

}

}

}, KeyPressEvent.getType());

}

private boolean isCapsLockOn(KeyPressEvent e) { return e.isShiftKeyDown() ^

Character.isUpperCase(e.getCharCode());

}

}

The extend() method gets the connector of the extended component as the parameter, in the above example a PasswordFieldConnector. It can access the widget with the getWidget().

An extension connector needs to be included in a widget set.The class must therefore be defined under the client package of a widget set, just like with component connectors.

16.8. Styling a Widget

To make your widget look stylish, you need to style it. There are two basic ways to define CSS styles for a component: in the widget sources and in a theme. A default style should be defined in the widget sources, and different themes can then modify the style.

16.8.1. Determining the CSS Class

The CSS class of a widget element is normally defined in the widget class and set with setStyleName(). A widget should set the styles for its sub-elements as it desires.

For example, you could style a composite widget with an overall style and with separate styles for the sub-widgets as follows:

public class MyPickerWidget extends ComplexPanel { public static final String CLASSNAME = "mypicker";

private final TextBox textBox = new TextBox();

private final PushButton button = new PushButton("...");

public MyPickerWidget() { setElement(Document.get().createDivElement()); setStylePrimaryName(CLASSNAME);

textBox.setStylePrimaryName(CLASSNAME + "-field"); button.setStylePrimaryName(CLASSNAME + "-button");

add(textBox, getElement()); add(button, getElement());

button.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) {

Window.alert("Calendar picker not yet supported!");

}

Styling a Widget

371