/******************************************************************************* * Copyright (c) 2012-2015 INRIA. * 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 * * Contributors: * Generoso Pagano - initial API and implementation ******************************************************************************/ package fr.inria.soctrace.framesoc.ui.dialogs; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import fr.inria.soctrace.framesoc.core.tools.management.ToolContributionManager; import fr.inria.soctrace.framesoc.core.tools.model.IFramesocTool; import fr.inria.soctrace.framesoc.core.tools.model.IFramesocTool.ParameterCheckStatus; import fr.inria.soctrace.framesoc.core.tools.model.IFramesocToolInput; import fr.inria.soctrace.framesoc.ui.input.AbstractToolInputComposite; import fr.inria.soctrace.framesoc.ui.input.AbstractToolInputCompositeFactory; import fr.inria.soctrace.framesoc.ui.input.FramesocToolInputContributionManager; import fr.inria.soctrace.framesoc.ui.listeners.ComboListener; import fr.inria.soctrace.lib.model.Tool; import fr.inria.soctrace.lib.model.utils.SoCTraceException; /** * Base Eclipse Dialog to launch tools * * @author "Generoso Pagano <generoso.pagano@inria.fr>" */ public abstract class AbstractLaunchToolDialog extends Dialog implements IArgumentDialog { // Constants public final static int MIN_HEIGHT = 380; public final static int MIN_WIDTH = 610; public final static int MIN_TOOL_INPUT_COMPOSITE_WIDTH = MIN_WIDTH - 45; // tool name -> tool object private Map<String, Tool> toolMap; // tool name -> framesoc tool private Map<String, IFramesocTool> fsToolMap; // the tool is null for non plugin tools // tool extension id -> composite factory private Map<String, AbstractToolInputCompositeFactory> factoryMap; // sorted tools private String[] sortedToolNames; // Tool Selection private ComboListener toolNameListener; private Label toolNameLabel; private Combo toolNameCombo; // Tool Message private Group groupMessage; private Text message; // Tool input composite. It must have a Grid Layout and Grid Data. private Composite inputComposite; // Custom tool input private AbstractToolInputComposite toolInputComposite; // Current selected tool, whose input composite is already displayed private Tool currentTool = null; // Dialog parent composite private Composite dialogParentComposite; public AbstractLaunchToolDialog(Shell parentShell, List<Tool> tools) throws SoCTraceException { super(parentShell); toolMap = new HashMap<String, Tool>(); fsToolMap = new HashMap<String, IFramesocTool>(); sortedToolNames = new String[tools.size()]; int i = 0; for (Tool t : tools) { sortedToolNames[i++] = t.getName(); toolMap.put(t.getName(), t); fsToolMap.put(t.getName(), ToolContributionManager.getToolLauncher(t)); } Arrays.sort(sortedToolNames); if (tools.size() > 0) { toolNameListener = new ComboListener(sortedToolNames[0]); } else { toolNameListener = new ComboListener(""); } factoryMap = FramesocToolInputContributionManager.getToolInputComposites(); } /** * Get the default input composite when there is no extension point for a tool. * * @param parent * composite parent * @param style * style * @return the default composite */ protected abstract AbstractToolInputComposite getDefaultToolInputComposite(Composite parent, int style); /** * @return the dialog title */ protected abstract String getDialogTitle(); /** * @return the dialog text */ protected abstract String getDialogText(); @Override protected Control createContents(Composite parent) { dialogParentComposite = parent; Control c = super.createContents(parent); layoutDialog(); return c; } @Override protected Control createDialogArea(final Composite parent) { this.getShell().setText(getDialogTitle()); Composite composite = (Composite) super.createDialogArea(parent); // *** Tool group *** Group toolGroup = new Group(composite, SWT.NONE); toolGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); toolGroup.setText(getDialogText()); toolGroup.setLayout(new GridLayout(1, true)); // Tool Composite importerComposite = new Composite(toolGroup, SWT.NONE); importerComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); importerComposite.setLayout(new GridLayout(2, false)); inputComposite = new Composite(toolGroup, SWT.NONE); inputComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1)); GridLayout gl_inputComposite = new GridLayout(1, false); gl_inputComposite.marginWidth = 0; inputComposite.setLayout(gl_inputComposite); toolNameLabel = new Label(importerComposite, SWT.NONE); toolNameLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); toolNameLabel.setText("Tool"); toolNameCombo = new Combo(importerComposite, SWT.BORDER | SWT.READ_ONLY); toolNameCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); for (String s : sortedToolNames) { toolNameCombo.add(s); } toolNameCombo.select(0); toolNameCombo.addSelectionListener(toolNameListener); toolNameCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateInputComposite(); updateOk(); layoutDialog(); } }); // Tool input updateInputComposite(); // *** Message group *** groupMessage = new Group(composite, SWT.V_SCROLL); groupMessage.setText("Tool message"); groupMessage.setLayout(new GridLayout(1, false)); groupMessage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); message = new Text(groupMessage, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY); GridData messageData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); messageData.minimumHeight = 80; message.setLayoutData(messageData); return composite; } private void updateInputComposite() { // aliasing check Tool t = getTool(); if (t.equals(currentTool)) { return; } currentTool = t; // clean all the composites in the input parent Control[] controls = inputComposite.getChildren(); for (Control c : controls) { c.dispose(); } if (factoryMap.containsKey(currentTool.getExtensionId())) { toolInputComposite = factoryMap.get(currentTool.getExtensionId()).getComposite( inputComposite, SWT.NONE); } else { toolInputComposite = getDefaultToolInputComposite(inputComposite, SWT.NONE); } toolInputComposite.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, true, 1, 1)); toolInputComposite.setArgumentDialog(this); toolInputComposite.layout(true); } private void layoutDialog() { Assert.isNotNull(inputComposite); GridData data = (GridData) inputComposite.getLayoutData(); /* * We set the min width to 0, we pack, then we set the correct min width and we pack again, * to force a redraw of the whole dialog even if nothing has changed. * * This fixes the following bug: if we change the tool, but the input composite used is an * instance of the same class as the previous, the new composite is not painted, since the * dialog thinks it is the same as before. */ data.minimumWidth = 0; dialogParentComposite.pack(); data.minimumWidth = MIN_TOOL_INPUT_COMPOSITE_WIDTH; dialogParentComposite.pack(); } @Override protected Point getInitialSize() { return new Point(MIN_WIDTH, MIN_HEIGHT); } @Override protected void createButtonsForButtonBar(Composite parent) { // create OK and Cancel buttons by default createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); // OK enabled only if the Framesoc tool says so updateOk(); } @Override public IFramesocToolInput getInput() { return toolInputComposite.getToolInput(); } @Override public void updateOk() { Button ok = getButton(IDialogConstants.OK_ID); if (ok == null) return; ParameterCheckStatus status = canLaunch(); message.setText(status.message); message.setToolTipText(status.message); ok.setEnabled(status.valid); } public Tool getTool() { return toolMap.get(toolNameListener.getText()); } private ParameterCheckStatus canLaunch() { ParameterCheckStatus status = new ParameterCheckStatus(false, ""); Tool t = getTool(); if (t == null) { status.message = "Importer not existing"; return status; } IFramesocTool tool = fsToolMap.get(t.getName()); if (tool == null) { status.message = "Importer not existing"; return status; } return tool.canLaunch(getInput()); } }