You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CreatingAComponentExtension.asciidoc 3.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. ---
  2. title: Creating A Component Extension
  3. order: 51
  4. layout: page
  5. ---
  6. [[creating-a-component-extension]]
  7. Creating a component extension
  8. ------------------------------
  9. In this tutorial we create a simple extension that can be attached to a
  10. `PasswordField`, displaying a floating notification if the user's Caps
  11. Lock seems to be enabled. We assume the reader is already familiar with
  12. the <<CreatingAUIExtension#creating-a-ui-extension,Creating a UI extension>>
  13. tutorial.
  14. This extension has almost no server-side functionality; the whole Extension
  15. class is as follows:
  16. [source,java]
  17. ....
  18. public class CapsLockWarning extends AbstractExtension {
  19. protected CapsLockWarning(PasswordField field) {
  20. // Non-public constructor to discourage direct instantiation
  21. extend(field);
  22. }
  23. public static CapsLockWarning warnFor(PasswordField field) {
  24. return new CapsLockWarning(field);
  25. }
  26. }
  27. ....
  28. When there's nothing to configure for the extension, users just want to
  29. enable it for some component and be done with it. By defining a static
  30. factory method, the user only needs to do something like
  31. `CapsLockWarning.warnFor(myPasswordField);` to make `myPasswordField`
  32. get the new functionality.
  33. The client side is not overly complicated, either. We override the
  34. `extend` method, called by the framework when the client-side extension
  35. connector is attached to its target the client-side counterpart of the
  36. connector to which the server-side extension instance is attached in
  37. this case, `PasswordFieldConnector`.
  38. We add a key press handler to the password widget, checking if the input
  39. looks like Caps Lock might be enabled. The Caps Lock state cannot be
  40. directly queried in GWT/JavaScript, so we use a trick: check if either
  41. * the shift key was not held but the entered character was uppercase, or
  42. * the shift key _was_ held but the entered character was lowercase.
  43. If this is the case, we show a warning in the form of a floating widget
  44. (`VOverlay`). This demonstrates how an extension may make use of UI
  45. elements even though it is not a part of the layout hierarchy. A
  46. frequent use case for extensions is showing different types of floating
  47. overlay elements that are temporary in character.
  48. [source,java]
  49. ....
  50. @Connect(CapsLockWarning.class)
  51. public class CapsLockWarningConnector extends AbstractExtensionConnector {
  52. @Override
  53. protected void extend(ServerConnector target) {
  54. final Widget passwordWidget = ((ComponentConnector) target).getWidget();
  55. final VOverlay warning = new VOverlay();
  56. warning.setOwner(passwordWidget);
  57. warning.add(new HTML("Caps Lock is enabled!"));
  58. passwordWidget.addDomHandler(new KeyPressHandler() {
  59. @Override
  60. public void onKeyPress(KeyPressEvent event) {
  61. if (isEnabled() && isCapsLockOn(event)) {
  62. warning.showRelativeTo(passwordWidget);
  63. } else {
  64. warning.hide();
  65. }
  66. }
  67. }, KeyPressEvent.getType());
  68. }
  69. private boolean isCapsLockOn(KeyPressEvent e) {
  70. return e.isShiftKeyDown() ^ Character.isUpperCase(e.getCharCode());
  71. }
  72. }
  73. ....
  74. To use the Caps Lock warning, compile your widgetset and extend a
  75. PasswordField with something like this
  76. [source,java]
  77. ....
  78. PasswordField field = new PasswordField("Enter your password");
  79. CapsLockWarning.warnFor(field);
  80. addComponent(field);
  81. ....