Do you have a need for custom components or behavior? This session will bring you the knowledge you require to create and extend custom components. Learn which calls to intercept for your custom logic.
2. CUSTOM COMPONENTS
Sven Brunken
sven@sencha.com @svenbrunken
Wednesday, November 2, 11
3. Overview
Widget vs Component
Important methods of the Widget class
When to use the Cell class?
Important methods of the Cell class
Questions
Wednesday, November 2, 11
5. Widget
Build on top of a DOM Element
Listens to browser events
Needs to be attached and detached for event handling
Does not solve the different sizing boxes
Can fire custom events through its HandlerManager
Wednesday, November 2, 11
6. Component
Extends the Widget class and so inherits all its features
Solves the different sizing boxes
Can be disabled directly
Can be positioned
Wednesday, November 2, 11
8. sinkEvents()
Defines which events can be listened to
Events not sunk cannot be listened to
public void sinkEvents(int eventBitsToAdd) {
if (isOrWasAttached()) {
DOM.sinkEvents(getElement(), eventBitsToAdd|DOM.getEventsSunk(getElement()));
} else {
eventsToSink |= eventBitsToAdd;
}
}
Wednesday, November 2, 11
9. onAttach()
Removes the event listener
Mandatory to enable browser event handling
Attaches the event listener of all its children widgets
protected void onAttach() {
attached = true;
DOM.setEventListener(getElement(), this);
int bitsToAdd = eventsToSink;
eventsToSink = -1;
if (bitsToAdd > 0) {
sinkEvents(bitsToAdd);
}
doAttachChildren();
onLoad();
AttachEvent.fire(this, true);
}
Wednesday, November 2, 11
10. onDetach()
Removes the event listener added from onAttach()
Browser events are no longer handled for this Widget
Prevents memory leaks
Detaches the event listener for all its children widgets
protected void onDetach() {
try {
onUnload();
AttachEvent.fire(this, false);
} finally {
try {
doDetachChildren();
} finally {
DOM.setEventListener(getElement(), null);
attached = false;
}
}
}
Wednesday, November 2, 11
11. fireEvent()
Fires a custom event through the HandlerManager
Other classes could listen to these events
public void fireEvent(GwtEvent<?> event) {
if (handlerManager != null) {
handlerManager.fireEvent(event);
}
}
Wednesday, November 2, 11
12. onBrowserEvent()
Only called when a Widget is attached
Gets called with the browser event that occurred
Refires the browser event through the HandlerManager
public void onBrowserEvent(Event event) {
DomEvent.fireNativeEvent(event, this, this.getElement());
}
Wednesday, November 2, 11
13. setElement()
Sets the element for this Widget
Mandatory to be called
An Element can only be set once and not changed
Needs to be called before calling getElement()
protected void setElement(Element elem) {
assert (element == null) : SETELEMENT_TWICE_ERROR;
this.element = elem;
}
Wednesday, November 2, 11
15. Gathering Information
What is the purpose of my custom widget?
Which browser events are required?
Can I extend an already existing class?
Do I understand all my requirements?
Wednesday, November 2, 11
17. The Class
Extending Component to overcome different sizing models
public class SquareWidget extends Component {
}
Wednesday, November 2, 11
18. Constructor
Setting the Element
Defining the events we want to listen to
public SquareWidget(Data data) {
this.data = data;
SquareWidgetTemplate t = GWT.create(SquareWidgetTemplate.class);
setElement(XDOM.create(t.render(data)));
sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONCLICK);
setPixelSize(100, 100);
}
Wednesday, November 2, 11
19. onBrowserEvent()
Contains our event handling logic
Should call the super method
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (event.getTypeInt() == Event.ONMOUSEOUT) {
onMouseOut(event);
} else if (event.getTypeInt() == Event.ONMOUSEOVER) {
onMouseOver(event);
} else if (event.getTypeInt() == Event.ONCLICK) {
onClick(event);
}
}
Wednesday, November 2, 11
20. onMouseOver()
getRelatedEventTarget returns the Element coming from
Setting the mouse over value
private void onMouseOver(Event event) {
EventTarget t = event.getRelatedEventTarget();
if (t == null || Element.is(t) && !getElement().isOrHasChild(Element.as(t))) {
String s = SafeHtmlUtils.fromString(data.getMouseOverName()).asString();
getContentElement().setInnerHTML(s);
}
}
Wednesday, November 2, 11
21. onMouseOut()
getRelatedEventTarget returns the Element moving to
Clearing the background color
Setting the standard value again
private void onMouseOut(Event event) {
EventTarget t = event.getRelatedEventTarget();
if (t == null
|| (Element.is(t) && !getElement().isOrHasChild(Element.as(t)))) {
getElement().getStyle().clearBackgroundColor();
String s = SafeHtmlUtils.fromString(data.getName()).asString();
getContentElement().setInnerHTML(s);
}
}
Wednesday, November 2, 11
22. onClick()
Sets the different background color
private void onClick(Event event) {
getElement().getStyle().setBackgroundColor("red");
}
Wednesday, November 2, 11
24. But, Do We Really
Require a Widget?
Wednesday, November 2, 11
25. Introducing Cell
Cells can handle browser events
Cells can be used in data components
Widgets cannot be used there
Cells render a lot faster
Wednesday, November 2, 11
26. Context of the Cell
Contains the relevant row and column index
Important when used in data widgets
Contains the key representing the value
Wednesday, November 2, 11
28. onBrowserEvent()
Gets called when an event for this cell occurred
Gets passed in the parent Element
Cell on its own does not know anything where it is displayed
One Cell can be displayed in many places
void onBrowserEvent(Context context, Element parent, C value,
NativeEvent event, ValueUpdater<C> valueUpdater);
Wednesday, November 2, 11
29. render()
Called when a Cell should be rendered
The output should be written to the SafeHtmlBuilder
void render(Context context, C value, SafeHtmlBuilder sb);
Wednesday, November 2, 11
30. getConsumedEvents()
Returns the events this cell requires
Cannot change in the lifecycle of a Cell
Set<String> getConsumedEvents();
Wednesday, November 2, 11
32. The Class
Extending AbstractCell
Implementing the Cell interface directly works too
public class SquareCell extends AbstractCell<Data> {
}
Wednesday, November 2, 11
33. Constructor
Defining the events this cell listens to
public SquareCell() {
super("click", "mouseover", "mouseout");
}
Wednesday, November 2, 11
34. onBrowserEvent()
Contains our event handling logic
public void onBrowserEvent(Context context, Element parent, Data value,
NativeEvent event, ValueUpdater<Data> valueUpdater) {
Element t = parent.getFirstChildElement();
Element target = event.getEventTarget().cast();
if (!t.isOrHasChild(target)) {
return;
}
if ("mouseout".equals(event.getType())) {
onMouseOut(context, parent, value, event);
} else if ("mouseover".equals(event.getType())) {
onMouseOver(context, parent, value, event);
} else if ("click".equals(event.getType())) {
onClick(context, parent, value, event);
}
}
Wednesday, November 2, 11
35. onMouseOver()
getRelatedEventTarget returns the Element coming from
Setting the mouse over value
private void onMouseOver(Context context, Element parent, Data value,
NativeEvent event) {
Element fc = parent.getFirstChildElement();
EventTarget t = event.getRelatedEventTarget();
if (t == null || (Element.is(t) && !fc.isOrHasChild(Element.as(t)))) {
String s = SafeHtmlUtils.fromString(value.getMouseOverName()).asString();
getContentElement(parent).setInnerHTML(s);
}
}
Wednesday, November 2, 11
36. onMouseOut()
getRelatedEventTarget returns the Element moving to
Clearing the background color
Setting the standard value again
private void onMouseOut(Context context, Element parent, Data value,
NativeEvent event) {
Element fc = parent.getFirstChildElement();
EventTarget t = event.getRelatedEventTarget();
if (t == null || (Element.is(t) && !fc.isOrHasChild(Element.as(t)))) {
fc.getStyle().clearBackgroundColor();
String s = SafeHtmlUtils.fromString(value.getName()).asString();
getContentElement(parent).setInnerHTML(s);
}
}
Wednesday, November 2, 11
37. onClick()
Sets the different background color
private void onClick(Context context, Element parent, Data value,
NativeEvent event) {
parent.getFirstChildElement().getStyle().setBackgroundColor("red");
}
Wednesday, November 2, 11