Java tutorial
/******************************************************************************* * 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); } }); } }