123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- ---
- title: Component and UI Extensions
- order: 7
- layout: page
- ---
-
- [[gwt.extension]]
- = 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 [classname]#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 components, 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.
-
- [[gwt.extension.server-side]]
- == Server-Side Extension API
-
- The server-side API for an extension consists of class that extends (in the Java
- sense) the [classname]#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, and illustrates the three alternative APIs:
-
- [source,java]
- ----
- public class CapsLockWarning extends AbstractExtension {
- // You could pass it in the constructor
- public CapsLockWarning(PasswordField field) {
- super.extend(field);
- }
-
- // Or in an extend() method
- public void extend(PasswordField field) {
- super.extend(field);
- }
-
- // Or with a static helper
- public static void addTo(PasswordField field) {
- new CapsLockWarning().extend(field);
- }
-
- // NOTE: you only need one of the above, not all of them
- }
- ----
-
- The extension could then be added to a component as follows:
-
- [source,java]
- ----
- PasswordField password = new PasswordField("Give it");
-
- // Use the constructor
- new CapsLockWarning(password);
-
- // ... or with the extend() method
- new CapsLockWarning().extend(password);
-
- // ... or with the static helper
- CapsLockWarning.addTo(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.
-
-
- [[gwt.extension.connector]]
- == Extension Connectors
-
- An extension does not have a corresponding widget on the client-side, but only
- an extension connector that extends the [classname]#AbstractExtensionConnector#
- class. The server-side extension class is specified with a
- [literal]#++@Connect++# annotation, just like in component connectors.
-
- An extension connector needs to implement the [methodname]#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.
-
- [source,java]
- ----
- @Connect(CapsLockWarning.class)
- public class CapsLockWarningConnector
- extends AbstractExtensionConnector {
-
- @Override
- protected void extend(ServerConnector target) {
- // Get the extended widget
- final Widget pw =
- ((ComponentConnector) target).getWidget();
-
- // Preparations for the added feature
- final VOverlay warning = new VOverlay();
- warning.setOwner(pw);
- 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 [methodname]#extend()# method gets the connector of the extended component
- as the parameter, in the above example a [classname]#PasswordFieldConnector#. It
- can access the widget with the [methodname]#getWidget()#.
-
- An extension connector needs to be included in a widget set. The class must
- therefore be defined under the [filename]#client# package of a widget set, just
- like with component connectors.
-
-
-
|