com.google.gdt.eclipse.designer.uibinder.model.widgets.UIObjectInfo.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gdt.eclipse.designer.uibinder.model.widgets.UIObjectInfo.java

Source

/*******************************************************************************
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * 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
 *
 * 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.gdt.eclipse.designer.uibinder.model.widgets;

import com.google.gdt.eclipse.designer.model.widgets.IUIObjectInfo;
import com.google.gdt.eclipse.designer.model.widgets.IUIObjectSizeSupport;
import com.google.gdt.eclipse.designer.model.widgets.support.DOMUtils;
import com.google.gdt.eclipse.designer.model.widgets.support.GwtState;
import com.google.gdt.eclipse.designer.model.widgets.support.UIObjectUtils;
import com.google.gdt.eclipse.designer.uibinder.model.util.NameProperty;
import com.google.gdt.eclipse.designer.uibinder.parser.UiBinderContext;
import com.google.gdt.eclipse.designer.uibinder.parser.UiBinderRenderer;

import org.eclipse.wb.draw2d.geometry.Insets;
import org.eclipse.wb.draw2d.geometry.Rectangle;
import org.eclipse.wb.draw2d.geometry.Translatable;
import org.eclipse.wb.internal.core.model.property.Property;
import org.eclipse.wb.internal.core.utils.execution.ExecutionUtils;
import org.eclipse.wb.internal.core.utils.execution.RunnableEx;
import org.eclipse.wb.internal.core.utils.execution.RunnableObjectEx;
import org.eclipse.wb.internal.core.utils.reflect.ReflectionUtils;
import org.eclipse.wb.internal.core.utils.ui.UiUtils;
import org.eclipse.wb.internal.core.xml.model.AbstractComponentInfo;
import org.eclipse.wb.internal.core.xml.model.EditorContext;
import org.eclipse.wb.internal.core.xml.model.creation.CreationSupport;
import org.eclipse.wb.internal.core.xml.model.description.ComponentDescription;
import org.eclipse.wb.internal.core.xml.model.utils.XmlObjectUtils;

import org.eclipse.swt.graphics.Image;

import org.apache.commons.lang.StringUtils;

import java.util.List;

/**
 * Model for <code>UiObject</code> in GWT UiBinder.
 * 
 * @author scheglov_ke
 * @coverage GWT.UiBinder.model
 */
public class UIObjectInfo extends AbstractComponentInfo implements IUIObjectInfo {
    private final Property m_variableProperty = new NameProperty(this);

    ////////////////////////////////////////////////////////////////////////////
    //
    // Constructor
    //
    ////////////////////////////////////////////////////////////////////////////
    public UIObjectInfo(EditorContext context, ComponentDescription description, CreationSupport creationSupport)
            throws Exception {
        super(context, description, creationSupport);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Access
    //
    ////////////////////////////////////////////////////////////////////////////
    @Override
    public UiBinderContext getContext() {
        return (UiBinderContext) super.getContext();
    }

    public final GwtState getState() {
        return getContext().getState();
    }

    /**
     * @return the {@link UIObjectUtils} to work with <code>UIObject</code>.
     */
    public final UIObjectUtils getUIObjectUtils() {
        return getState().getUIObjectUtils();
    }

    /**
     * @return the {@link DOMUtils} to work with <code>Element</code>.
     */
    public final DOMUtils getDOM() {
        return getState().getDomUtils();
    }

    @Override
    public Rectangle getAbsoluteBounds() {
        return m_absoluteBounds;
    }

    /**
     * @return the DOM margins.
     */
    public final Insets getMargins() {
        return m_margins;
    }

    /**
     * @return the DOM borders.
     */
    public final Insets getBorders() {
        return m_borders;
    }

    /**
     * @return the DOM paddings.
     */
    public final Insets getPaddings() {
        return m_paddings;
    }

    /**
     * @return the underlying DOM <code>Element</code>.
     */
    public Object getDOMElement() throws Exception {
        return getState().getUIObjectUtils().getElement(getObject());
    }

    /**
     * @return <code>true</code> if this {@link UIObjectInfo} has no visible border, so artificial
     *         border should be drawn.
     */
    @Override
    public boolean shouldDrawDotsBorder() {
        return ExecutionUtils.runObjectIgnore(new RunnableObjectEx<Boolean>() {
            public Boolean runObject() throws Exception {
                String script = XmlObjectUtils.getParameter(UIObjectInfo.this, "shouldDrawBorder");
                if (!StringUtils.isEmpty(script)) {
                    return (Boolean) XmlObjectUtils.executeScript(UIObjectInfo.this, script);
                }
                return false;
            }
        }, false);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Size
    //
    ////////////////////////////////////////////////////////////////////////////
    private final UIObjectSizeSupport m_sizeSupport = new UIObjectSizeSupport(this);

    public final IUIObjectSizeSupport getSizeSupport() {
        return m_sizeSupport;
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Life cycle
    //
    ////////////////////////////////////////////////////////////////////////////
    @Override
    protected final void saveEdit() throws Exception {
        super.saveEdit();
        getContext().saveFormEditor();
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Properties
    //
    ////////////////////////////////////////////////////////////////////////////
    @Override
    protected List<Property> getPropertyList() throws Exception {
        List<Property> properties = super.getPropertyList();
        properties.add(m_sizeSupport.getSizeProperty());
        properties.add(m_variableProperty);
        return properties;
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Refresh
    //
    ////////////////////////////////////////////////////////////////////////////
    private List<Object> m_liveProcessHiddenWidgets;

    @Override
    public void refresh_dispose() throws Exception {
        // GWT does not allow any operation after disposing GWTState
        if (getState().isDisposed()) {
            return;
        }
        // clear RootPanel
        if (isRoot()) {
            getUIObjectUtils().clearRootPanel();
        }
        // dispose children
        super.refresh_dispose();
    }

    @Override
    public void refresh_beforeCreate() throws Exception {
        call_Impl_enter();
        super.refresh_beforeCreate();
    }

    @Override
    protected void refresh_create() throws Exception {
        UiBinderRenderer renderer = new UiBinderRenderer(this);
        renderer.render();
    }

    @Override
    protected void refresh_afterCreate() throws Exception {
        super.refresh_afterCreate();
        if (isRoot()) {
            UIObjectUtils utils = getUIObjectUtils();
            Object liveWidget = utils.getLiveWidget();
            if (liveWidget != null) {
                m_liveProcessHiddenWidgets = utils.hideRootPanelWidgets(liveWidget);
            }
        }
    }

    @Override
    protected void refresh_afterCreate2() throws Exception {
        super.refresh_afterCreate2();
        call_Impl_exit();
    }

    @Override
    protected void refresh_finish() throws Exception {
        super.refresh_finish();
        if (isRoot()) {
            if (m_liveProcessHiddenWidgets != null) {
                UIObjectUtils.showWidgets(m_liveProcessHiddenWidgets);
                m_liveProcessHiddenWidgets = null;
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Impl life cycle
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * Call enter() as if this UI was create as result of call from JavaScript.
     */
    private void call_Impl_enter() {
        if (isRoot()) {
            ExecutionUtils.runIgnore(new RunnableEx() {
                public void run() throws Exception {
                    ClassLoader classLoader = getContext().getClassLoader();
                    Class<?> class_Impl = classLoader.loadClass("com.google.gwt.core.client.impl.Impl");
                    ReflectionUtils.invokeMethod(class_Impl, "enter()");
                }
            });
        }
    }

    /**
     * Call exit() as if this UI was create as result of call from JavaScript.
     */
    private void call_Impl_exit() {
        if (isRoot()) {
            ExecutionUtils.runIgnore(new RunnableEx() {
                public void run() throws Exception {
                    ClassLoader classLoader = getContext().getClassLoader();
                    Class<?> class_Impl = classLoader.loadClass("com.google.gwt.core.client.impl.Impl");
                    ReflectionUtils.invokeMethod(class_Impl, "exit(boolean)", true);
                }
            });
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Refresh: fetch
    //
    ////////////////////////////////////////////////////////////////////////////
    private Rectangle m_absoluteBounds;
    protected Insets m_margins;
    protected Insets m_borders;
    protected Insets m_paddings;

    @Override
    protected void refresh_fetch() throws Exception {
        Object element = getDOMElement();
        // check for messages loop
        if (isRoot()) {
            if (requiresMessagesLoop()) {
                for (int i = 0; i < 5; i++) {
                    getState().runMessagesLoop();
                    Thread.sleep(1);
                }
            }
        }
        // prepare bounds
        fetchBounds(element);
        // prepare image
        if (isRoot()) {
            fetchImage(element);
        }
        // prepare parent-relative bounds
        {
            Rectangle parentBounds = new Rectangle(m_absoluteBounds);
            if (getParent() instanceof AbstractComponentInfo) {
                AbstractComponentInfo parent = (AbstractComponentInfo) getParent();
                Rectangle parentAbsoluteBounds = parent.getAbsoluteBounds();
                parentBounds.x -= parentAbsoluteBounds.x;
                parentBounds.y -= parentAbsoluteBounds.y;
            } else {
                parentBounds.x = parentBounds.y = 0;
            }
            setBounds(parentBounds);
        }
        // borders/margins/paddings
        fetchSpacing();
        // continue for children
        super.refresh_fetch();
    }

    protected void fetchBounds(Object element) throws Exception {
        m_absoluteBounds = fetchAbsoluteBounds(element);
        {
            Rectangle bounds = m_absoluteBounds.getCopy();
            if (getParent() instanceof AbstractComponentInfo) {
                AbstractComponentInfo parent = (AbstractComponentInfo) getParent();
                Rectangle parentAbsoluteBounds = parent.getAbsoluteBounds();
                bounds.x -= parentAbsoluteBounds.x;
                bounds.y -= parentAbsoluteBounds.y;
                bounds.translate(parent.getClientAreaInsets().getNegated());
            }
            setModelBounds(bounds);
        }
    }

    protected Rectangle fetchModelBounds(Object element) {
        return getState().getModelBounds(element);
    }

    protected Rectangle fetchAbsoluteBounds(Object element) {
        Rectangle absoluteBounds = getState().getAbsoluteBounds(element);
        // Case 43858: https://fogbugz.instantiations.com/default.php?43858
        if (isRoot()) {
            if (absoluteBounds.x < 0) {
                absoluteBounds.x = 0;
            }
            if (absoluteBounds.y < 0) {
                absoluteBounds.y = 0;
            }
        }
        return absoluteBounds;
    }

    protected void fetchImage(Object element) throws Exception {
        GwtState state = getState();
        Image browserScreenshot = state.createBrowserScreenshot();
        // prepare bounds of image
        Rectangle imageBounds = m_absoluteBounds;
        if (state.isStrictMode() && state.isBrowserExplorer()) {
            imageBounds = imageBounds.getTranslated(2, 2);
        }
        // set image
        Image objectImage = UiUtils.getCroppedImage(browserScreenshot, imageBounds.getSwtRectangle());
        setImage(objectImage);
    }

    /**
     * @return <code>true</code> if this {@link UIObjectInfo} or one of its children require running
     *         messages loop before {@link #refresh_fetch()}, to finalize rendering.
     */
    private boolean requiresMessagesLoop() {
        for (UIObjectInfo child : getChildren(UIObjectInfo.class)) {
            if (child.requiresMessagesLoop()) {
                return true;
            }
        }
        {
            String script = XmlObjectUtils.getParameter(this, "GWT.requiresMessagesLoop");
            return getUIObjectUtils().evaluateScriptBoolean(script);
        }
    }

    /**
     * Fetch spacing of UI Object.
     */
    protected void fetchSpacing() throws Exception {
        GwtState state = getState();
        Object element = getDOMElement();
        m_margins = state.getMargins(element);
        m_borders = state.getBorders(element);
        m_paddings = state.getPaddings(element);
        // prepare "clientAreaInsets"
        if (!getState().isBody(element)) {
            fetchClientAreaInsets();
        }
    }

    /**
     * Fetches "client area insets". Usually "margins + borders", but complex components may require
     * special handling.
     */
    protected void fetchClientAreaInsets() throws Exception {
        Insets insets = new Insets();
        insets.add(m_margins);
        insets.add(m_borders);
        setClientAreaInsets(insets);
    }

    /**
     * Transforms given absolute {@link Translatable} into this {@link UIObjectInfo} relative.
     */
    public final void absoluteToRelative(Translatable translatable) {
        translatable.translate(-m_absoluteBounds.x, -m_absoluteBounds.y);
    }

    /**
     * Transforms given absolute {@link Translatable} into this {@link UIObjectInfo} model.
     */
    public final void absoluteToModel(Translatable translatable) {
        absoluteToRelative(translatable);
        {
            Insets clientAreaInsets = getClientAreaInsets();
            translatable.translate(-clientAreaInsets.left, -clientAreaInsets.top);
        }
    }
}