/* * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file 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.amazonaws.eclipse.lambda.project.wizard.util; import static com.amazonaws.eclipse.core.ui.wizards.WizardWidgetFactory.newFillingLabel; import static com.amazonaws.eclipse.core.ui.wizards.WizardWidgetFactory.newGroup; import static com.amazonaws.eclipse.core.ui.wizards.WizardWidgetFactory.newLink; import static com.amazonaws.eclipse.lambda.model.LambdaFunctionDataModel.P_CLASS_NAME; import static com.amazonaws.eclipse.lambda.model.LambdaFunctionDataModel.P_INPUT_TYPE; import static com.amazonaws.eclipse.lambda.model.LambdaFunctionDataModel.P_PACKAGE_NAME; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.beans.PojoObservables; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer; import org.eclipse.jdt.internal.ui.text.SimpleJavaSourceViewerConfiguration; import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jdt.ui.text.IJavaPartitions; import org.eclipse.jdt.ui.text.JavaTextTools; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.Document; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import com.amazonaws.eclipse.core.validator.PackageNameValidator; import com.amazonaws.eclipse.core.widget.ComboComplex; import com.amazonaws.eclipse.core.widget.TextComplex; import com.amazonaws.eclipse.databinding.NotEmptyValidator; import com.amazonaws.eclipse.lambda.UrlConstants; import com.amazonaws.eclipse.lambda.blueprint.BlueprintsProvider; import com.amazonaws.eclipse.lambda.blueprint.LambdaBlueprint; import com.amazonaws.eclipse.lambda.blueprint.LambdaBlueprintsConfig; import com.amazonaws.eclipse.lambda.model.LambdaFunctionDataModel; import com.amazonaws.eclipse.lambda.project.template.CodeTemplateManager; import com.amazonaws.eclipse.lambda.project.template.data.LambdaBlueprintTemplateData; import freemarker.template.Template; import freemarker.template.TemplateException; @SuppressWarnings("restriction") public class LambdaFunctionComposite { private final Composite parentComposite; private final LambdaFunctionDataModel dataModel; private final LambdaBlueprintsConfig lambdaBlueprintConfig; private final DataBindingContext dataBindingContext; private TextComplex packageNameComplex; private TextComplex classNameComplex; private ComboComplex inputTypeComplex; private Link handlerTypeDescriptionLink; private JavaSourceViewer sourcePreview; private Document sourcePreviewDocument; private Group group; private Composite inputComposite; public LambdaFunctionComposite(Composite parentComposite, LambdaFunctionDataModel dataModel, DataBindingContext dataBindingContext) { this.parentComposite = parentComposite; this.dataModel = dataModel; this.dataBindingContext = dataBindingContext; this.lambdaBlueprintConfig = BlueprintsProvider.provideLambdaBlueprints(); createControl(); } public void createControl() { group = newGroup(parentComposite, "Lambda Function Handler"); GridLayout groupLayout = new GridLayout(1, true); groupLayout.marginWidth = 15; group.setLayout(groupLayout); String description = "Each Lambda function must specify a handler class " + "which the service will use as the entry point to begin execution."; setItalicFont(newLink(group, UrlConstants.webLinkListener, description + " <a href=\"" + UrlConstants.LAMBDA_JAVA_HANDLER_DOC_URL + "\">Learn more</a> about Lambda Java function handler.", 1)); inputComposite = new Composite(group, SWT.NONE); inputComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); GridLayout inputCompLayout = new GridLayout(3, true); inputCompLayout.marginHeight = 10; inputCompLayout.marginWidth = 10; inputComposite.setLayout(inputCompLayout); } public void createPackageNameControl() { this.packageNameComplex = TextComplex.builder() .composite(inputComposite) .dataBindingContext(dataBindingContext) .pojoObservableValue(PojoObservables.observeValue(dataModel, P_PACKAGE_NAME)) .validator(new PackageNameValidator("Package name must be provided!")) .labelValue("Package Name:") .defaultValue(dataModel.getPackageName()) .textColSpan(2) .build(); } public void createClassNameControl() { this.classNameComplex = TextComplex.builder() .composite(inputComposite) .dataBindingContext(dataBindingContext) .pojoObservableValue(PojoObservables.observeValue(dataModel, P_CLASS_NAME)) .validator(new NotEmptyValidator("Please provide a valid class name for the handler")) .labelValue("Class Name:") .defaultValue(dataModel.getClassName()) .textColSpan(2) .build(); } public void createInputTypeControl() { this.inputTypeComplex = ComboComplex.<LambdaBlueprint> builder() .composite(inputComposite) .dataBindingContext(dataBindingContext) .pojoObservableValue(PojoObservables.observeValue(dataModel, P_INPUT_TYPE)) .labelValue("Input Type:") .items(lambdaBlueprintConfig.getBlueprints().values()) .defaultItemName(dataModel.getInputType()) .comboColSpan(2) .build(); handlerTypeDescriptionLink = newLink(inputComposite, UrlConstants.webLinkListener, dataModel.getSelectedBlueprint().getDescription(), 3); setItalicFont(handlerTypeDescriptionLink); } public void createSeparator() { Label separator = new Label(group, SWT.HORIZONTAL | SWT.SEPARATOR); separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); } public TextComplex getPackageNameComplex() { return packageNameComplex; } public void createHandlerSourcePreview() { newFillingLabel(group, "Preview:", 1); sourcePreviewDocument = new Document(""); IPreferenceStore javaPluginPrefStore = JavaPlugin.getDefault() .getCombinedPreferenceStore(); sourcePreview = new JavaSourceViewer(group, null, null, false, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER, javaPluginPrefStore); sourcePreview.setEditable(false); sourcePreview.getTextWidget().setFont(JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT)); // Setting up Java Syntax Highlight JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools(); tools.setupJavaDocumentPartitioner(sourcePreviewDocument, IJavaPartitions.JAVA_PARTITIONING); SimpleJavaSourceViewerConfiguration sourceConfig = new SimpleJavaSourceViewerConfiguration( tools.getColorManager(), javaPluginPrefStore, null, IJavaPartitions.JAVA_PARTITIONING, true); sourcePreview.configure(sourceConfig); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); gridData.horizontalSpan = 1; gridData.heightHint = 50; sourcePreview.getTextWidget().setLayoutData(gridData); sourcePreview.setDocument(sourcePreviewDocument); dataModel.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { onPropertyChange(); } }); } private void onPropertyChange() { Template template = CodeTemplateManager.getInstance().getLambdaHandlerTemplate( dataModel.getSelectedBlueprint()); LambdaBlueprintTemplateData freeMarkerDataModel = dataModel.collectLambdaBlueprintTemplateData(); if (template == null || freeMarkerDataModel == null) { return; } handlerTypeDescriptionLink.setText(dataModel.getSelectedBlueprint().getDescription()); String source; try { source = CodeTemplateManager.processTemplateWithData(template, freeMarkerDataModel); } catch (TemplateException | IOException e) { throw new RuntimeException("Failed to generate handler source preview", e); } if (sourcePreviewDocument != null) { sourcePreviewDocument.set(source); } if (sourcePreview != null) { sourcePreview.getTextWidget().setRedraw(true); } } public void initialize() { onPropertyChange(); } private Font italicFont; private void setItalicFont(Control control) { FontData[] fontData = control.getFont() .getFontData(); for (FontData fd : fontData) { fd.setStyle(SWT.ITALIC); } italicFont = new Font(Display.getDefault(), fontData); control.setFont(italicFont); } public void dispose() { if (italicFont != null) { italicFont.dispose(); } } }