io.pelle.mango.client.gwt.modules.dictionary.controls.EditTextCellWithValidation.java Source code

Java tutorial

Introduction

Here is the source code for io.pelle.mango.client.gwt.modules.dictionary.controls.EditTextCellWithValidation.java

Source

/**
 * Copyright (c) 2013 Christian Pelster.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Christian Pelster - initial API and implementation
 */
package io.pelle.mango.client.gwt.modules.dictionary.controls;

import io.pelle.mango.client.base.modules.dictionary.controls.IBaseControl;
import io.pelle.mango.client.base.modules.dictionary.model.controls.IBaseControlModel;
import io.pelle.mango.client.gwt.GwtStyles;
import io.pelle.mango.client.web.modules.dictionary.controls.BaseDictionaryControl;

import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.safecss.shared.SafeStyles;
import com.google.gwt.safecss.shared.SafeStylesBuilder;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.client.SafeHtmlTemplates.Template;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.text.shared.SafeHtmlRenderer;
import com.google.gwt.text.shared.SimpleSafeHtmlRenderer;

public class EditTextCellWithValidation<T> extends BaseCellControl<T> {

    interface Template extends SafeHtmlTemplates {
        @Template("<input style=\"{1}\" type=\"text\" value=\"{0}\" tabindex=\"-1\"></input>")
        SafeHtml input(String value, SafeStyles styles);

        @Template("<span style=\"{1}\">{0}</span>")
        SafeHtml display(String value, SafeStyles styles);
    }

    private static Template template;

    private final BaseDictionaryControl<IBaseControlModel, Object> baseControl;

    private final SafeHtmlRenderer<String> renderer;

    public EditTextCellWithValidation(BaseDictionaryControl<IBaseControlModel, Object> baseControl) {
        super(baseControl.getModel(), ClickEvent.getType().getName(), KeyUpEvent.getType().getName(),
                KeyDownEvent.getType().getName(), FocusEvent.getType().getName(), BlurEvent.getType().getName());

        if (template == null) {
            template = GWT.create(Template.class);
        }

        this.baseControl = baseControl;
        this.renderer = SimpleSafeHtmlRenderer.getInstance();
    }

    @Override
    public void onBrowserEvent(Context context, Element parent, T value, NativeEvent event,
            ValueUpdater<T> valueUpdater) {
        GWT.log("onBrowserEvent: value: " + value.toString());

        String type = event.getType();
        int keyCode = event.getKeyCode();

        boolean enterPressed = KeyUpEvent.getType().getName().equals(type) && keyCode == KeyCodes.KEY_ENTER;
        boolean startEdit = ClickEvent.getType().getName().equals(type) || enterPressed;
        boolean eventTargetIsInput = false;

        if (Element.is(event.getEventTarget())) {
            Element target = Element.as(event.getEventTarget());
            GWT.log("target: " + target.getTagName() + "(" + target.getId() + "), eventType: " + type);

            eventTargetIsInput = "input".equals(target.getTagName().toLowerCase());

        }

        if (BlurEvent.getType().getName().equals(type)) {
            if (eventTargetIsInput) {
                commit(context, parent, valueUpdater);
            }

        } else if (FocusEvent.getType().getName().equals(type)) {
            getInputElement(parent).focus();
        } else {
            if (isEditing(context, parent, value)) {
                editEvent(context, parent, value, event, valueUpdater);

            } else {
                if (startEdit) {
                    startEdit(context, parent, value);
                }
            }
        }

    }

    @Override
    public void render(Context context, T value, SafeHtmlBuilder sb) {
        ViewData<T> viewData = getOrInitViewData(context);

        SafeStylesBuilder styles = new SafeStylesBuilder();

        if (getBaseControl(context).getValidationMessages().hasErrors()) {
            styles.appendTrustedString(GwtStyles.CELL_ERROR_STYLE);
        }

        if (viewData.isEditing()) {
            sb.append(template.input(getBaseControl(context).format(), styles.toSafeStyles()));
        } else {
            styles.appendTrustedString(GwtStyles.CELL_ERROR_DISPLAY_PADDING);
            sb.append(template.display(renderer.render(getBaseControl(context).format()).asString(),
                    styles.toSafeStyles()));
        }
    }

    @Override
    public boolean resetFocus(Context context, Element parent, T value) {
        if (isEditing(context, parent, value)) {
            getInputElement(parent).focus();
            return true;
        }
        return false;
    }

    protected void startEdit(Context context, Element parent, T value) {
        ViewData<T> viewData = getOrInitViewData(context);
        viewData.setEditing(true);

        setValue(context, parent, value);

        focus(parent);
    }

    private void focus(Element parent) {
        InputElement input = getInputElement(parent);

        input.focus();
        input.select();
    }

    private void cancel(Context context, Element parent, T value) {
        clearInput(getInputElement(parent));
        setValue(context, parent, value);
    }

    private native void clearInput(Element input) /*-{
                                                  if (input.selectionEnd)
                                                  input.selectionEnd = input.selectionStart;
                                                  else if ($doc.selection)
                                                  $doc.selection.clear();
                                                  }-*/;

    private void commit(Context context, Element parent, ValueUpdater<T> valueUpdater) {
        ViewData<T> viewData = getOrInitViewData(context);
        viewData.setEditing(false);

        IBaseControl<?, ?> baseControl = getBaseControl(context);
        baseControl.parseValue(getInputElement(parent).getValue());

        clearInput(getInputElement(parent));

        setValue(context, parent, getBaseControl(context).getValue());
    }

    private void editEvent(Context context, Element parent, T value, NativeEvent event,
            ValueUpdater<T> valueUpdater) {
        ViewData<T> viewData = getOrInitViewData(context);
        String type = event.getType();

        boolean keyUp = KeyUpEvent.getType().getName().equals(type);
        boolean keyDown = KeyDownEvent.getType().getName().equals(type);

        if (keyUp || keyDown) {
            int keyCode = event.getKeyCode();

            if (keyUp && keyCode == KeyCodes.KEY_ENTER) {
                commit(context, parent, valueUpdater);
            } else if (keyUp && keyCode == KeyCodes.KEY_ESCAPE) {
                if (viewData.isEditingAgain()) {
                    viewData.setEditing(false);
                } else {
                    clearViewData(context);
                }

                cancel(context, parent, value);
            } else {
                // Update the text in the view data on each key.
                updateViewData(context, parent, viewData, true);
            }
        }
    }

    private void updateViewData(Context context, Element parent, ViewData<T> viewData, boolean isEditing) {
        viewData.setEditing(isEditing);

    }
}