Wednesday, 21 August 2013

Gwt - EditTextCell to look exactly like TextInputCell

Gwt - EditTextCell to look exactly like TextInputCell

I have cellTable (GWT) which uses TextInputCell to allow the user to Edit
cells. When a user first selects a textbox,it receives focus and the user
can edit the data. When the user then tries to select another textbox, the
previous textbox loses focus but the newly selected textbox does not
receive focus. Clicking on the box again gives it focus. EditTextCell does
the same functionality, it allows us to edit the cell in 1 click, but it
is difficult to identify the cell as editableuntil or unless you click on
it.
As shown in the showcase, Can we modify the existing EditTextCell to look
exactly like TextInputCell? Can somebody help me in modifying it?
Below is the code of EditTextCell (ref here)
/**
* An editable text cell. Click to edit, escape to cancel, return to commit.
*/
public class EditTextCell extends
AbstractEditableCell<String, EditTextCell.ViewData> {
interface Template extends SafeHtmlTemplates {
@Template("<input type=\"text\" value=\"{0}\" tabindex=\"-1\"></input>")
SafeHtml input(String value);
}
/**
* The view data object used by this cell. We need to store both the
text and
* the state because this cell is rendered differently in edit mode. If
we did
* not store the edit state, refreshing the cell with view data would
always
* put us in to edit state, rendering a text box instead of the new text
* string.
*/
static class ViewData {
private boolean isEditing;
/**
* If true, this is not the first edit.
*/
private boolean isEditingAgain;
/**
* Keep track of the original value at the start of the edit, which
might be
* the edited value from the previous edit and NOT the actual value.
*/
private String original;
private String text;
/**
* Construct a new ViewData in editing mode.
*
* @param text the text to edit
*/
public ViewData(String text) {
this.original = text;
this.text = text;
this.isEditing = true;
this.isEditingAgain = false;
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
ViewData vd = (ViewData) o;
return equalsOrBothNull(original, vd.original)
&& equalsOrBothNull(text, vd.text) && isEditing == vd.isEditing
&& isEditingAgain == vd.isEditingAgain;
}
public String getOriginal() {
return original;
}
public String getText() {
return text;
}
@Override
public int hashCode() {
return original.hashCode() + text.hashCode()
+ Boolean.valueOf(isEditing).hashCode() * 29
+ Boolean.valueOf(isEditingAgain).hashCode();
}
public boolean isEditing() {
return isEditing;
}
public boolean isEditingAgain() {
return isEditingAgain;
}
public void setEditing(boolean isEditing) {
boolean wasEditing = this.isEditing;
this.isEditing = isEditing;
// This is a subsequent edit, so start from where we left off.
if (!wasEditing && isEditing) {
isEditingAgain = true;
original = text;
}
}
public void setText(String text) {
this.text = text;
}
private boolean equalsOrBothNull(Object o1, Object o2) {
return (o1 == null) ? o2 == null : o1.equals(o2);
}
}
private static Template template;
private final SafeHtmlRenderer<String> renderer;
/**
* Construct a new EditTextCell that will use a
* {@link SimpleSafeHtmlRenderer}.
*/
public EditTextCell() {
this(SimpleSafeHtmlRenderer.getInstance());
}
/**
* Construct a new EditTextCell that will use a given {@link
SafeHtmlRenderer}
* to render the value when not in edit mode.
*
* @param renderer a {@link SafeHtmlRenderer SafeHtmlRenderer<String>}
* instance
*/
public EditTextCell(SafeHtmlRenderer<String> renderer) {
super(CLICK, KEYUP, KEYDOWN, BLUR);
if (template == null) {
template = GWT.create(Template.class);
}
if (renderer == null) {
throw new IllegalArgumentException("renderer == null");
}
this.renderer = renderer;
}
@Override
public boolean isEditing(Context context, Element parent, String value) {
ViewData viewData = getViewData(context.getKey());
return viewData == null ? false : viewData.isEditing();
}
@Override
public void onBrowserEvent(Context context, Element parent, String value,
NativeEvent event, ValueUpdater<String> valueUpdater) {
Object key = context.getKey();
ViewData viewData = getViewData(key);
if (viewData != null && viewData.isEditing()) {
// Handle the edit event.
editEvent(context, parent, value, viewData, event, valueUpdater);
} else {
String type = event.getType();
int keyCode = event.getKeyCode();
boolean enterPressed = KEYUP.equals(type)
&& keyCode == KeyCodes.KEY_ENTER;
if (CLICK.equals(type) || enterPressed) {
// Go into edit mode.
if (viewData == null) {
viewData = new ViewData(value);
setViewData(key, viewData);
} else {
viewData.setEditing(true);
}
edit(context, parent, value);
}
}
}
@Override
public void render(Context context, String value, SafeHtmlBuilder sb) {
// Get the view data.
Object key = context.getKey();
ViewData viewData = getViewData(key);
if (viewData != null && !viewData.isEditing() && value != null
&& value.equals(viewData.getText())) {
clearViewData(key);
viewData = null;
}
if (viewData != null) {
String text = viewData.getText();
if (viewData.isEditing()) {
/*
* Do not use the renderer in edit mode because the value of a text
* input element is always treated as text. SafeHtml isn't valid
in the
* context of the value attribute.
*/
sb.append(template.input(text));
} else {
// The user pressed enter, but view data still exists.
sb.append(renderer.render(text));
}
} else if (value != null) {
sb.append(renderer.render(value));
}
}
@Override
public boolean resetFocus(Context context, Element parent, String value) {
if (isEditing(context, parent, value)) {
getInputElement(parent).focus();
return true;
}
return false;
}
/**
* Convert the cell to edit mode.
*
* @param context the {@link Context} of the cell
* @param parent the parent element
* @param value the current value
*/
protected void edit(Context context, Element parent, String value) {
setValue(context, parent, value);
InputElement input = getInputElement(parent);
input.focus();
input.select();
}
/**
* Convert the cell to non-edit mode.
*
* @param context the context of the cell
* @param parent the parent Element
* @param value the value associated with the cell
*/
private void cancel(Context context, Element parent, String value) {
clearInput(getInputElement(parent));
setValue(context, parent, value);
}
/**
* Clear selected from the input element. Both Firefox and IE fire spurious
* onblur events after the input is removed from the DOM if selection is
not
* cleared.
*
* @param input the input element
*/
private native void clearInput(Element input) /*-{
if (input.selectionEnd)
input.selectionEnd = input.selectionStart;
else if ($doc.selection)
$doc.selection.clear();
}-*/;
/**
* Commit the current value.
*
* @param context the context of the cell
* @param parent the parent Element
* @param viewData the {@link ViewData} object
* @param valueUpdater the {@link ValueUpdater}
*/
private void commit(Context context, Element parent, ViewData viewData,
ValueUpdater<String> valueUpdater) {
String value = updateViewData(parent, viewData, false);
clearInput(getInputElement(parent));
setValue(context, parent, viewData.getOriginal());
if (valueUpdater != null) {
valueUpdater.update(value);
}
}
private void editEvent(Context context, Element parent, String value,
ViewData viewData, NativeEvent event, ValueUpdater<String>
valueUpdater) {
String type = event.getType();
boolean keyUp = KEYUP.equals(type);
boolean keyDown = KEYDOWN.equals(type);
if (keyUp || keyDown) {
int keyCode = event.getKeyCode();
if (keyUp && keyCode == KeyCodes.KEY_ENTER) {
// Commit the change.
commit(context, parent, viewData, valueUpdater);
} else if (keyUp && keyCode == KeyCodes.KEY_ESCAPE) {
// Cancel edit mode.
String originalText = viewData.getOriginal();
if (viewData.isEditingAgain()) {
viewData.setText(originalText);
viewData.setEditing(false);
} else {
setViewData(context.getKey(), null);
}
cancel(context, parent, value);
} else {
// Update the text in the view data on each key.
updateViewData(parent, viewData, true);
}
} else if (BLUR.equals(type)) {
// Commit the change. Ensure that we are blurring the input element and
// not the parent element itself.
EventTarget eventTarget = event.getEventTarget();
if (Element.is(eventTarget)) {
Element target = Element.as(eventTarget);
if ("input".equals(target.getTagName().toLowerCase())) {
commit(context, parent, viewData, valueUpdater);
}
}
}
}
/**
* Get the input element in edit mode.
*/
private InputElement getInputElement(Element parent) {
return parent.getFirstChild().<InputElement> cast();
}
/**
* Update the view data based on the current value.
*
* @param parent the parent element
* @param viewData the {@link ViewData} object to update
* @param isEditing true if in edit mode
* @return the new value
*/
private String updateViewData(Element parent, ViewData viewData,
boolean isEditing) {
InputElement input = (InputElement) parent.getFirstChild();
String value = input.getValue();
viewData.setText(value);
viewData.setEditing(isEditing);
return value;
}
}

No comments:

Post a Comment