com.google.gdt.eclipse.designer.model.widgets.panels.AbsolutePanelInfo.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gdt.eclipse.designer.model.widgets.panels.AbsolutePanelInfo.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.model.widgets.panels;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.gdt.eclipse.designer.model.widgets.WidgetInfo;

import org.eclipse.wb.core.editor.IContextMenuConstants;
import org.eclipse.wb.core.model.JavaInfo;
import org.eclipse.wb.core.model.ObjectInfo;
import org.eclipse.wb.core.model.broadcast.ObjectEventListener;
import org.eclipse.wb.draw2d.geometry.Dimension;
import org.eclipse.wb.draw2d.geometry.Point;
import org.eclipse.wb.draw2d.geometry.Rectangle;
import org.eclipse.wb.internal.core.DesignerPlugin;
import org.eclipse.wb.internal.core.EnvironmentUtils;
import org.eclipse.wb.internal.core.model.JavaInfoUtils;
import org.eclipse.wb.internal.core.model.clipboard.ClipboardCommand;
import org.eclipse.wb.internal.core.model.creation.CreationSupport;
import org.eclipse.wb.internal.core.model.description.ComponentDescription;
import org.eclipse.wb.internal.core.model.description.ToolkitDescription;
import org.eclipse.wb.internal.core.model.layout.absolute.IPreferenceConstants;
import org.eclipse.wb.internal.core.model.layout.absolute.OrderingSupport;
import org.eclipse.wb.internal.core.model.property.converter.IntegerConverter;
import org.eclipse.wb.internal.core.model.util.AbsoluteLayoutCreationFlowSupport;
import org.eclipse.wb.internal.core.model.util.ObjectInfoAction;
import org.eclipse.wb.internal.core.model.util.TemplateUtils;
import org.eclipse.wb.internal.core.utils.ast.AstEditor;
import org.eclipse.wb.internal.core.utils.ast.DomGenerics;
import org.eclipse.wb.internal.core.utils.ast.StatementTarget;
import org.eclipse.wb.internal.core.utils.check.Assert;

import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;

import org.apache.commons.lang.StringUtils;

import java.util.List;

/**
 * Model for GWT <code>AbsolutePanel</code>.
 * 
 * @author scheglov_ke
 * @coverage gwt.model
 */
public class AbsolutePanelInfo extends ComplexPanelInfo implements IAbsolutePanelInfo<WidgetInfo> {
    private final AbsolutePanelInfo m_this = this;

    ////////////////////////////////////////////////////////////////////////////
    //
    // Constructor
    //
    ////////////////////////////////////////////////////////////////////////////
    public AbsolutePanelInfo(AstEditor editor, ComponentDescription description, CreationSupport creationSupport)
            throws Exception {
        super(editor, description, creationSupport);
        contributeWidgetContextMenu();
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Context menu
    //
    ////////////////////////////////////////////////////////////////////////////
    private void contributeWidgetContextMenu() {
        addBroadcastListener(new ObjectEventListener() {
            @Override
            public void addContextMenu(List<? extends ObjectInfo> objects, ObjectInfo object, IMenuManager manager)
                    throws Exception {
                if (object instanceof WidgetInfo && object.getParent() == m_this) {
                    WidgetInfo component = (WidgetInfo) object;
                    contributeWidgetContextMenu(manager, component);
                }
            }
        });
    }

    /**
     * Contributes {@link Action}'s into {@link WidgetInfo} context menu.
     */
    private void contributeWidgetContextMenu(IMenuManager manager, final WidgetInfo widget) {
        // order
        {
            List<WidgetInfo> widgets = getChildrenWidgets();
            new OrderingSupport(widgets, widget).contributeActions(manager);
        }
        // auto-size
        {
            IAction action = new ObjectInfoAction(widget, "Autosize widget",
                    DesignerPlugin.getImageDescriptor("info/layout/absolute/fit_to_size.png")) {
                @Override
                protected void runEx() throws Exception {
                    widget.getSizeSupport().setSize(null);
                }
            };
            manager.appendToGroup(IContextMenuConstants.GROUP_CONSTRAINTS, action);
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Commands
    //
    ////////////////////////////////////////////////////////////////////////////
    public void command_BOUNDS(WidgetInfo widget, Point location, Dimension size) throws Exception {
        Assert.isTrue(getChildren().contains(widget), "%s is not child of %s.", widget, this);
        if (size != null) {
            widget.getSizeSupport().setSize(size);
        }
        if (location != null) {
            setLocation(widget, location);
        }
        // check creation flow
        if (location != null && (widget.getModelBounds() != null || EnvironmentUtils.isTestingTime())
                && useCreationFlow()) {
            AbsoluteLayoutCreationFlowSupport.apply(this, getChildrenWidgets(), widget, location, size);
        }
    }

    /**
     * Modifies location of {@link WidgetInfo}.
     * 
     * @param location
     *          new location, not <code>null</code>.
     */
    private void setLocation(WidgetInfo widget, Point location) throws Exception {
        Assert.isNotNull(location);
        String xString = IntegerConverter.INSTANCE.toJavaSource(this, location.x);
        String yString = IntegerConverter.INSTANCE.toJavaSource(this, location.y);
        String xyString = ", " + xString + ", " + yString;
        boolean locationSet = false;
        boolean force_setWidgetPosition = JavaInfoUtils.hasTrueParameter(widget,
                "GWT.AbsolutePanel: force setWidgetPosition");
        // add(%widget%,int,int)
        for (MethodInvocation invocation : getInvocations("add(%widget%,int,int)", widget)) {
            setExpression(invocation, 1, xString);
            setExpression(invocation, 2, yString);
            locationSet = true;
        }
        // setWidgetLocation(%widget%,int,int)
        for (MethodInvocation invocation : getInvocations("setWidgetPosition(%widget%,int,int)", widget)) {
            setExpression(invocation, 1, xString);
            setExpression(invocation, 2, yString);
            locationSet = true;
        }
        // if no location set yet, try to update add()
        if (!locationSet && !force_setWidgetPosition) {
            for (MethodInvocation invocation : getInvocations("add(%widget%)", widget)) {
                AstEditor editor = getEditor();
                String argsSource = editor.getSource(DomGenerics.arguments(invocation).get(0));
                argsSource += xyString;
                editor.replaceInvocationArguments(invocation, ImmutableList.of(argsSource));
                locationSet = true;
                // related nodes
                addRelatedNodes(invocation);
                widget.addRelatedNodes(invocation);
            }
        }
        // if no location set yet, add setWidgetPosition()
        if (!locationSet) {
            // prepare target (after association)
            StatementTarget target;
            {
                Statement associationStatement = widget.getAssociation().getStatement();
                target = new StatementTarget(associationStatement, false);
            }
            // add invocation
            String source = TemplateUtils.format("{0}.setWidgetPosition({1}{2})", this, widget, xyString);
            Expression expression = widget.addExpressionStatement(target, source);
            addRelatedNodes(expression);
        }
    }

    private boolean useCreationFlow() {
        return getToolkit().getPreferences().getBoolean(IPreferenceConstants.P_CREATION_FLOW);
    }

    private ToolkitDescription getToolkit() {
        return getDescription().getToolkit();
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Utils
    //
    ////////////////////////////////////////////////////////////////////////////
    /**
     * @return {@link MethodInvocation}'s of this {@link JavaInfo}, where one of the arguments is
     *         given {@link WidgetInfo}.
     * 
     * @param signature
     *          the signature of method, with <code>%widget%</code> at place where {@link WidgetInfo}
     *          argument is expected.
     */
    private List<MethodInvocation> getInvocations(String signature, WidgetInfo widget) {
        // analyze/update signature
        int widgetIndex;
        {
            int widgetPatternIndex = signature.indexOf("%widget%");
            Assert.isTrue(widgetPatternIndex != -1, "No %%widget%% in %s.", signature);
            widgetIndex = StringUtils.countMatches(signature.substring(0, widgetPatternIndex), ",");
            signature = StringUtils.replace(signature, "%widget%", "com.google.gwt.user.client.ui.Widget");
        }
        // filter MethodInvocation's
        List<MethodInvocation> invocations = Lists.newArrayList();
        for (MethodInvocation invocation : getMethodInvocations(signature)) {
            Expression widgetExpression = DomGenerics.arguments(invocation).get(widgetIndex);
            if (widget.isRepresentedBy(widgetExpression)) {
                invocations.add(invocation);
            }
        }
        return invocations;
    }

    /**
     * Set the argument of {@link MethodInvocation} to given source.
     */
    private void setExpression(MethodInvocation invocation, int index, String arg) throws Exception {
        getEditor().replaceExpression(DomGenerics.arguments(invocation).get(index), arg);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Clipboard
    //
    ////////////////////////////////////////////////////////////////////////////
    @Override
    protected void clipboardCopy_addWidgetCommands(WidgetInfo widget, List<ClipboardCommand> commands)
            throws Exception {
        final Rectangle modelBounds = widget.getModelBounds();
        commands.add(new PanelClipboardCommand<AbsolutePanelInfo>(widget) {
            private static final long serialVersionUID = 0L;

            @Override
            protected void add(AbsolutePanelInfo panel, WidgetInfo widget) throws Exception {
                panel.command_CREATE2(widget, null);
                panel.command_BOUNDS(widget, modelBounds.getLocation(), null);
            }
        });
    }
}