Creating GWT Component
Creating Custom WidgetSet
Jmix framework provides a ready-compiled widgetset in the jmix-ui-widgets-compiled
artifact.
To create a custom widgetset in the project, you need to:
-
Remove
implementation 'io.jmix.ui:jmix-ui-widgets-compiled'
dependency. -
Add dependencies to your
build.gradle
:implementation 'io.jmix.ui:jmix-ui-widgets' (1) widgets 'io.jmix.ui:jmix-ui-widgets'
1 Required only for developing custom client-side components. -
Add the
compileWidgets
task (change paths according to your application base package):compileWidgets { generate "ui.ex1.widgets.CustomWidgetSet" includePaths('**/io/jmix/**/widget/**', '**/ui/ex1/widgets/**') }
The
excludePaths
andincludePaths
parameters for thecompileWidgets
task are useful if you don’t want to compile a widgetset in case, for example, some screen is changed.The
excludePaths
parameter is used to exclude some paths or files from the widgetset compilation. See the example:compileWidgets { generate 'com.company.demo.widgets.CustomWidgetSet' excludePaths('**/com/company/demo/**') }
Thus, changes in the
com.company.demo
package do not trigger the widgetset compilation.The
includePaths
parameter is used to include some paths or files to the widgetset compilation.See the example:
compileWidgets { generate 'com.company.demo.widgets.CustomWidgetSet' includePaths('**/io/jmix/**/widget/**', '**/com/company/demo/widgets/**') }
Thus, changes in the
com.company.demo.widgets
package and in anywidget
package (including sub-packages) under theio.jmix
package trigger the widgetset compilation. Other changes, for example, in screen controllers or XML descriptors do not trigger such compilation. If you see unexpected re-compilation, check the particular reason (executecompileWidgets
with the--info
parameter).The
excludePaths
andincludePaths
parameters accept the list of string patterns.Patterns may include:
-
*
to match any number of characters. -
?
to match any single character. -
**
to match any number of directories or files.
Either
'/'
or'\'
may be used in a pattern to separate directories.For example,
includePaths('**/com/company/demo/widgets/**')
includes all files in thecom/company/demo/widgets
directory including subdirectories.More information is available at https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/util/PatternFilterable.html.
-
-
Add the
jmix.ui.widget-set
property to yourapplication.properties
file (adjust location according to thecompileWidgets
task above):jmix.ui.widget-set=ui.ex1.widgets.CustomWidgetSet
Widgetsets are compiled by the WidgetsCompile
task named compileWidgets
. It is automatically created when using the Jmix plugin.
The compiled widgetset is placed in the build/widgets
directory and will be included in the JAR/WAR artifact of the project.
Creating ColorButton GWT Component
In this section, we will create a custom ColorButton
component. This component is directly inherited from the JmixButton
component.
Custom UI components (that is, components directly inherited from Vaadin components) should be placed in the widgets
subpackage, for example, com.company.sample.widgets
. Clients-side components (connectors and widgets), as well as classes used for server-side and client-side communication, such as RPC and State, should be placed in the widgets.client
subpackage, for example com.company.sample.widgets.client
. More information about client-server integration can be found in the Vaadin documentation.
Creating Component State Class
Create ColorButtonState.java
within the widgets.client
package.
The ColorButtonState
state class defines what data is sent between the client and the server. It contains public fields that are automatically serialized on the server-side and deserialized on the client.
public class ColorButtonState extends JmixButtonState {
public String color = "";
}
Creating Vaadin Component Class
ColorButton
is a Vaadin component class. It can define an API for the server code, accessor methods, event listeners, and data sources connection. Developers use the methods of this class in the application code.
Create ColorButton.java
within the widgets
package:
public class ColorButton extends JmixButton {
@Override
protected ColorButtonState getState() {
return (ColorButtonState) super.getState();
}
@Override
protected ColorButtonState getState(boolean markAsDirty) {
return (ColorButtonState) super.getState(markAsDirty);
}
public String getColor() {
return getState(false).color;
}
public void setColor(String color) {
if (!Objects.equals(getState(false).color, color)) {
getState().color = color;
}
}
}
Creating Connector
Create ColorButtonConnector.java
within the widgets.client
package.
The ColorButtonConnector
connector links client code with the server.
@Connect(ColorButton.class) (1)
public class ColorButtonConnector extends JmixButtonConnector {
@Override
public ColorButtonState getState() {
return (ColorButtonState) super.getState(); (2)
}
@Override
public void onStateChanged(StateChangeEvent event) { (3)
super.onStateChanged(event);
if (event.hasPropertyChanged("color")) { (4)
Style style = getWidget().getElement().getStyle();
style.setBackgroundColor(getState().color);
style.setBackgroundImage("none");
}
}
}
1 | With this annotation the ColorButtonConnector connector is marked to have a server-side counterpart. The value of the annotation is ColorButton - the class of server-side implementation . |
2 | Returns the ColorButtonState object for this connector. |
3 | Reacts on server state change. |
4 | Refreshes the widget’s style if the value on server has changed. |
Using ColorButton
To demonstrate how the component works, let’s create a new color-button-screen
screen.
Open the ColorButtonScreen.java
screen controller and add the code that puts the component to the screen:
@UiController("sample_ColorButtonScreen")
@UiDescriptor("color-button-screen.xml")
public class ColorButtonScreen extends Screen {
@Subscribe
protected void onInit(InitEvent event) {
ColorButton button = new ColorButton(); (1)
button.setCaption("Button");
button.setColor("#AFEEEE");
getWindow().unwrap(Layout.class).addComponent(button); (2)
}
}
1 | Initializes a color button component instance. |
2 | Retrieves a link to the Vaadin container using the unwrap() method, and adds the new component to it. |
The picture below shows the project structure:
Start the application and see the result: