com.google.api.explorer.client.parameter.schema.ObjectElement.java Source code

Java tutorial

Introduction

Here is the source code for com.google.api.explorer.client.parameter.schema.ObjectElement.java

Source

/*
 * Copyright (C) 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.api.explorer.client.parameter.schema;

import com.google.api.explorer.client.base.Schema;
import com.google.api.explorer.client.parameter.schema.SchemaForm.SchemaEditor;
import com.google.common.annotations.VisibleForTesting;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.json.client.JSONNull;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Encapsulates the key/value of one key/value pair in an
 * {@link ObjectSchemaEditor}.
 *
 * @author jasonhall@google.com (Jason Hall)
 */
public class ObjectElement extends Composite implements SchemaEditor, HasRemovalHandlers {

    private static RowUiBinder uiBinder = GWT.create(RowUiBinder.class);

    interface RowUiBinder extends UiBinder<Widget, ObjectElement> {
    }

    @UiField
    Panel panel;
    @UiField
    InlineLabel label;
    @UiField
    InlineLabel nullText;
    @UiField
    HTMLPanel placeholder;
    @UiField
    Image remove;
    @UiField
    Image info;
    @UiField
    Label nullify;
    @UiField
    PopupPanel docsTooltip;
    @UiField
    PopupPanel patchTooltip;
    @UiField
    PopupPanel deleteTooltip;
    @UiField
    Label description;
    @UiField
    Label required;

    @VisibleForTesting
    final SchemaEditor innerEditor;

    final String key;
    private boolean isNull;
    private boolean isNullable;

    private final HandlerManager handlerManager = new HandlerManager(this);

    /**
     * Creates an instance.
     *
     * @param key Key in the object under which this object can be found.
     * @param editor Editor which should be shown for the value portion of the object element.
     * @param property Schema which is used to represent values of this object element.
     * @param isRemovable Whether or not this object can request to be removed from the object.
     * @param isNullable Whether or not the object can be explicitly set to null.
     */
    public ObjectElement(String key, SchemaEditor editor, Schema property, boolean isRemovable,
            boolean isNullable) {

        initWidget(uiBinder.createAndBindUi(this));
        this.key = key;
        this.innerEditor = editor;
        this.isNullable = isNullable;

        label.setText("\"" + key + "\"");

        info.setVisible(!isRemovable || property.getDescription() != null);
        required.setVisible(!isRemovable);
        remove.setVisible(isRemovable);
        description.setVisible(property.getDescription() != null);
        description.setText(property.getDescription());

        // Default to showing the editor.
        isNull = false;
        updateDisplay();

        placeholder.add(editor.render(property));

        // Initialize the tooltip popup.
        docsTooltip.show();
        docsTooltip.hide();

        // Initialize the patch tooltip popup.
        patchTooltip.show();
        patchTooltip.hide();

        // Initialize the delete tooltip popup.
        deleteTooltip.show();
        deleteTooltip.hide();
    }

    @UiHandler("nullText")
    void activateInnerEditor(ClickEvent event) {
        isNull = false;
        updateDisplay();
    }

    @UiHandler("nullify")
    void nullifyValue(ClickEvent event) {
        isNull = true;
        updateDisplay();
    }

    private void updateDisplay() {
        nullText.setVisible(isNull);
        nullify.setVisible(!isNull && isNullable);
        placeholder.setVisible(!isNull);

        // If the editor is not an Object or Array editor, it can contain inner
        // elements, and will have its own inner remove link to manage them. If
        // that's the case, move the remove link to after the editor.
        if (!innerEditor.isComposite() || isNull) {
            moveControlsAfterEditor();
        } else {
            moveEditorAfterControls();
        }
    }

    @UiHandler("info")
    void discloseInfo(ClickEvent event) {
        EditorHelper.discloseLowerRight(docsTooltip, info);
    }

    @UiHandler("info")
    void discloseInfoHover(MouseOverEvent event) {
        EditorHelper.discloseLowerRight(docsTooltip, info);
    }

    @UiHandler("info")
    void hideInfoHover(MouseOutEvent event) {
        docsTooltip.hide();
    }

    @UiHandler("nullify")
    void disclosePatchInfo(MouseOverEvent event) {
        EditorHelper.discloseLowerRight(patchTooltip, nullify);
    }

    @UiHandler("nullify")
    void disclosePatchInfo(MouseOutEvent event) {
        patchTooltip.hide();
    }

    @UiHandler("remove")
    void removeClicked(ClickEvent event) {
        // Fire the remove event.
        handlerManager.fireEvent(new ClickEvent() {
        });
    }

    @UiHandler("remove")
    void discloseRemoveHover(MouseOverEvent event) {
        EditorHelper.discloseLowerRight(deleteTooltip, remove);
    }

    @UiHandler("remove")
    void hideRemoveHover(MouseOutEvent event) {
        deleteTooltip.hide();
    }

    private void moveControlsAfterEditor() {
        // By removing these widgets and re-adding them we move them to the end of the object panel.
        panel.remove(info);
        panel.remove(nullify);
        panel.remove(remove);

        // The order that these objects are added determines their order next to the element, and should
        // match the order from the declarative layout.
        panel.add(info);
        panel.add(nullify);
        panel.add(remove);
    }

    private void moveEditorAfterControls() {
        // By removing these widgets and re-adding them we move them to the end of the object panel.
        panel.remove(placeholder);
        panel.add(placeholder);
    }

    @Override
    public Widget render(Schema property) {
        return this;
    }

    @Override
    public JSONValue getJSONValue() {
        return isNull ? JSONNull.getInstance() : innerEditor.getJSONValue();
    }

    @Override
    public void setJSONValue(JSONValue value) {
        if (value.isNull() != null) {
            isNull = true;
        } else {
            isNull = false;
            innerEditor.setJSONValue(value);
        }
        updateDisplay();
    }

    @Override
    public void prettyPrint(StringBuilder resultSoFar, int indentation) {
        if (isNull) {
            resultSoFar.append("null");
        } else {
            innerEditor.prettyPrint(resultSoFar, indentation);
        }
    }

    @Override
    public boolean isComposite() {
        return innerEditor.isComposite();
    }

    @Override
    public HandlerRegistration registerRemoveClickedHandler(ClickHandler handler) {
        return handlerManager.addHandler(ClickEvent.getType(), handler);
    }
}