GWT Custom Widgets
GWT Custom Widgets
Overview
Big Idea
• Wrap multiple widgets in a container
– Usually a Panel
• Give extra behavior
– Behavior that is more than the individual behaviors of the sub-
widgets.
• E.g., in example below, unchecking checkbox disables the
textfield.
• Make methods to pass settings through to
underlying widgets
– So programmers can control look of the individual pieces
• Example result
– End user sees a checkbox and textfield
– GWT sees a FlowPanel
14
Basic Steps: Summary
1. Extend Composite
– public class OptionalTextBox extends Composite
2. Call initWidget(container) in constructor
– FlowPanel panel = new FlowPanel();
– initWidget(panel);
3. Assign CSS style names to new widget
– setStyleName("some-documented-css-name");
4. Make methods to control new behavior
– Methods for high-level behavior of new widget
5. Make pass-through methods
– To control look of individual pieces
15 6. Use in your code like any other widget
17
20
© 2013 Marty Hall & Yaakov Chaikin
Example:
OptionalTextBox
...
public class OptionalTextBox extends Composite {
private TextBox textBox = new TextBox();
Internal widgets hidden from clients
private CheckBox checkBox = new CheckBox();
private boolean checkedEnablesText;
24
Step 3: Assign CSS style names
...
private boolean checkedEnablesText;
...
public OptionalTextBox(String caption,
boolean checkedEnablesText,
boolean isChecked) {
this.checkedEnablesText = checkedEnablesText;
FlowPanel panel = new FlowPanel(); Set style class names for entire widget.
Equivalent to panel.setStyleName(…)
initWidget(panel);
setStyleName("core-opt-text-widget");
textBox.setStyleName("core-opt-textbox"); Expose styling of internal
widgets to clients.
checkBox.setStyleName("core-opt-checkbox");
panel.add(checkBox);
panel.add(textBox);
...
}
...
25
27
28
Step 6: Use Widget Normally
(HTML Page)
...
<fieldset>
<legend>Optional Textbox 1</legend>
<div id="optional-textbox-1"></div>
</fieldset>
<br/>
<fieldset>
<legend>Optional Textbox 2</legend>
<div id="optional-textbox-2"></div>
</fieldset>
<br/>
...
29
OptionalTextBox optTextBox2 =
new OptionalTextBox
("Check if Male or Female. If neither, "
+ "explain PLEASE!!!", false, true);
RootPanel.get("optional-textbox-2").add(optTextBox2);
...
}
30
Style Sheet
...
When enabled, show green border around
.core-opt-text-widget .core-opt-textbox { the textbox.
margin-left: 5px;
border: #3F9 solid 1px;
}
.core-opt-text-widget .core-opt-textbox-disabled {
border: #CCC solid 1px;
When disabled, display grey border.
}
#optional-textbox-1 .core-opt-text-widget,
#optional-textbox-2 .core-opt-text-widget,
#optional-textbox-3 .core-opt-text-widget {
width: 530px;
} Ensure internal widgets don’t slide on top
of each other if browser window is made
... too small, i.e., always stay this minimum
width.
31
Example: Result
Initial state
32
© 2013 Marty Hall & Yaakov Chaikin
34
HTML Page
...
<fieldset>
<legend>Optional Textbox 1</legend>
<div id="optional-textbox-1"></div>
</fieldset>
<br/>
...
<fieldset>
<legend>Optional Textbox 3</legend>
<div id="optional-textbox-3"></div>
</fieldset>
<br/>
...
35
EntryPoint Class
public class GwtCustomWidgets1 implements EntryPoint {
36
CSS File
...
#optional-textbox-1 .core-opt-text-widget,
#optional-textbox-2 .core-opt-text-widget,
#optional-textbox-3 .core-opt-text-widget {
width: 530px;
}
#optional-textbox-3 .core-opt-text-widget .core-opt-checkbox
{
margin-bottom: 3px;
display: block;
} TextBox is already a block-level
element, but the way GWT
implements CheckBox is through
<span>, so need to force it to be a
block-level element.
37
Example: Result
38
© 2013 Marty Hall & Yaakov Chaikin
Motivation
• Modularizing your project is always good
– Promotes what we all learned in CS101:
Unit of code should do one thing and do it well
• Allows your functionality to be reused in
other modules and projects
– Without unnecessary baggage
– Ideal if you want create a GWT widget library and
distribute it
• Team role separation
• Separate building and testing
– Faster compilation and development
40
Basic Steps
1. Create new GWT Web Application Project
– Do not let Eclipse generate project sample code
2. Create new GWT Module
– Module name can be anything, but usually same as name
of the Eclipse project
– Usually, no need to specify entry-point in
Module.gwt.xml as this module will not be runnable
• We’ll just include it in another (runnable) module
3. Develop custom widget as usual in new
module
41
FancyOptionalTextBox Example:
Create New GWT Web Project
44
FancyOptionalTextBox Example:
Create New GWT Web Project
Right-click on GwtCustomWidgets2 project in
Eclipse, choose New Module
45
FancyOptionalTextBox Example:
Create New GWT Web Project (Cont.)
46
FancyOptionalTextBox Example:
GwtCustomWidgets2.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "…"
<module>
<inherits name="com.google.gwt.user.User" />
<source path="browser" />
</module>
47
FancyOptionalTextBox Example:
FancyOptionalTextBox.java
package coreservlets.browser.widget;
Code to be translated to JavaScript code now
... must reside inside .browser package.
public class FancyOptionalTextBox extends Composite {
...
private String previousText = "";
...
public FancyOptionalTextBox(String caption, boolean
checkedEnablesText, boolean isChecked) {
this.checkedEnablesText = checkedEnablesText;
FlowPanel panel = new FlowPanel();
initWidget(panel);
setStyleName("core-opt-text-widget");
textBox.setStyleName("core-opt-textbox");
checkBox.setStyleName("core-opt-checkbox");
panel.add(checkBox);
panel.add(textBox); Constructor is the same as in OptionalTextBox
checkBox.setText(caption);
checkBox.setValue(isChecked);
enableTextBox(checkedEnablesText, isChecked);
checkBox.addClickHandler(new CheckBoxHandler());
48 }
FancyOptionalTextBox Example:
FancyOptionalTextBox.java (con)
private void enableTextBox(boolean checkedEnables,
boolean isChecked) {
boolean enable = (checkedEnables && isChecked)
|| (!checkedEnables && !isChecked);
textBox.setStyleDependentName("disabled", !enable);
clearOrRestoreTextBox(enable);
textBox.setEnabled(enable);
}
...
49
FancyOptionalTextBox Example:
FancyOptionalTextBox.java (con)
public void setCaption(String caption) {
checkBox.setText(caption);
}
51
FancyOptionalTextBox Example:
Import as Java JAR
Refresh GwtCustomWidgets1 project (select it and
press F5).
52
FancyOptionalTextBox Example:
GwtCustomWidgets1.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='gwtcustomwidgets1'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name='coreservlets.GwtCustomWidgets2'/>
<entry-point
class='coreservlets.client.GwtCustomWidgets1'/>
Note: it’s a bad idea for this module to place code into
.browser package without explicitly declaring it here.
53
FancyOptionalTextBox Example:
GwtCustomWidgets1 EntryPoint
package coreservlets.client;
...
public class GwtCustomWidgets1 implements EntryPoint {
54
FancyOptionalTextBox Example:
Result (Development Mode)
• Initially checked, we fill in some text
• Then, uncheck the checkbox – clears and disables
textbox
• Then, check the checkbox again – enables and
restores previously entered text
55
FancyOptionalTextBox Example:
Result (Hosted Mode)
GWT-compiled GwtCustomWidgets1 project
56
© 2013 Marty Hall & Yaakov Chaikin
Wrap-Up
Summary
• First, consider using 3rd-party widget library
– But evaluate carefully, esp. if causes changes in GWT approach
• When making your own components
1. Extend Composite
• public class OptionalTextBox extends Composite
2. Call initWidget(container) in constructor
• FlowPanel panel = new FlowPanel();
• initWidget(panel);
3. Assign CSS style names to new widget
• setStyleName("some-documented-css-name");
4. Make methods to control new behavior
• Methods for high-level behavior of new widget
5. Make pass-through methods
• To control look of individual pieces
6. Use in your code like any other widget
58
© 2013 Marty Hall & Yaakov Chaikin
Questions?
JSF 2, PrimeFaces, Java 7 or 8, Ajax, jQuery, Hadoop, RESTful Web Services, Android, HTML5, Spring, Hibernate, Servlets, JSP, GWT, and other Java EE training.