/******************************************************************************* * Copyright (c) 2009, 2017 xored software, Inc. and others. * * 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: * xored software, Inc. - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.tcl.internal.tclchecker.ui.preferences; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.dltk.compiler.util.Util; import org.eclipse.dltk.core.environment.IEnvironment; import org.eclipse.dltk.core.environment.IFileHandle; import org.eclipse.dltk.tcl.internal.tclchecker.impl.IEnvironmentPredicate; import org.eclipse.dltk.tcl.tclchecker.model.configs.CheckerEnvironmentInstance; import org.eclipse.dltk.tcl.tclchecker.model.configs.CheckerInstance; import org.eclipse.dltk.tcl.tclchecker.model.configs.CheckerVersion; import org.eclipse.dltk.ui.dialogs.StatusInfo; import org.eclipse.dltk.ui.environment.EnvironmentContainer; import org.eclipse.dltk.ui.environment.IEnvironmentUI; import org.eclipse.dltk.ui.util.PixelConverter; import org.eclipse.dltk.ui.util.SWTFactory; import org.eclipse.dltk.utils.PlatformFileUtils; import org.eclipse.dltk.validators.configs.ValidatorEnvironmentInstance; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; public class TclCheckerInstanceBlock extends AbstractValidatorEditBlock { private EnvironmentContainer environments; private IEnvironmentPredicate environmentPredicate; private CheckerInstance instance; private CheckerEnvironmentInstance environmentInstance; @Override protected void doInit(IValidatorDialogContext context, Object object) { this.environments = context.getEnvironments(); this.environmentPredicate = context.getEnvironmentPredicate(); this.instance = (CheckerInstance) object; } private Text nameField; private Combo versionField; private TableViewer environmentField; private Text pathField; private Text cliField; private Button noPCX; private ListViewer pcxList; private Button pcxAdd; private Button pcxBrowse; private Button pcxRemove; @Override public void createControl(Composite parent) { final GridLayout contentLayout = new GridLayout(2, false); contentLayout.marginWidth = 0; contentLayout.marginHeight = 0; parent.setLayout(contentLayout); final Composite nameComposite = new Composite(parent, SWT.NONE); final GridData nameLayoutData = new GridData(GridData.FILL_HORIZONTAL); nameLayoutData.horizontalSpan = 2; nameComposite.setLayoutData(nameLayoutData); final GridLayout nameLayout = new GridLayout(2, false); nameLayout.marginWidth = 0; nameLayout.marginHeight = 0; nameComposite.setLayout(nameLayout); createName(nameComposite); createVersion(nameComposite); createCommandLineOptions(nameComposite); SWTFactory.createHorizontalSpacer(nameComposite, 2); SWTFactory.createLabel(parent, Messages.TclCheckerInstanceDialog_Environment, 2); final Composite hostList = new Composite(parent, SWT.NONE); final GridData hostListLayoutData = new GridData(GridData.FILL_VERTICAL); hostListLayoutData.widthHint = new PixelConverter(parent).convertWidthInCharsToPixels(25); hostList.setLayoutData(hostListLayoutData); final GridLayout hostListLayout = new GridLayout(1, false); hostListLayout.marginWidth = 0; hostListLayout.marginHeight = 0; hostList.setLayout(hostListLayout); createEnvironment(hostList); final Composite right = new Composite(parent, SWT.NONE); right.setLayoutData(new GridData(GridData.FILL_BOTH)); final GridLayout rightLayout = new GridLayout(3, false); rightLayout.marginWidth = 0; rightLayout.marginHeight = 0; rightLayout.marginLeft = 5; right.setLayout(rightLayout); createPath(right); createPCXGroup(right); } private void createName(Composite parent) { SWTFactory.createLabel(parent, Messages.TclCheckerInstanceDialog_Name, 1); nameField = SWTFactory.createText(parent, SWT.BORDER, 1, Util.EMPTY_STRING); nameField.addModifyListener(e -> validate()); } private void createEnvironment(Composite parent) { Composite environmentFieldParent = new Composite(parent, SWT.NONE); environmentFieldParent.setLayoutData(new GridData(GridData.FILL_BOTH)); final TableColumnLayout environmentTableLayout = new TableColumnLayout(); environmentFieldParent.setLayout(environmentTableLayout); environmentField = new TableViewer(environmentFieldParent, SWT.BORDER); environmentTableLayout.setColumnData(new TableColumn(environmentField.getTable(), SWT.LEFT), new ColumnWeightData(100)); environmentField.setLabelProvider(new LabelProvider() { @Override public String getText(Object element) { if (element instanceof String) { return environments.getName((String) element); } return super.getText(element); } }); environmentField.setContentProvider(new IStructuredContentProvider() { @Override public void dispose() { // NOP } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // NOP } @Override public Object[] getElements(Object inputElement) { if (inputElement instanceof String[]) { return (String[]) inputElement; } return new Object[0]; } }); environmentField.addSelectionChangedListener(event -> { if (isBusy()) return; final ISelection selection = event.getSelection(); if (selection != null && !selection.isEmpty() && selection instanceof IStructuredSelection) { final IStructuredSelection ss = (IStructuredSelection) selection; if (ss.size() == 1) { environmentInstance = instance.getEnvironment((String) ss.getFirstElement()); refreshEnvironmentFields(); return; } } environmentInstance = null; refreshEnvironmentFields(); }); environments.addChangeListener(() -> { ++busy; try { final ISelection selection = environmentField.getSelection(); final String[] ids = collectEnvironments(); environmentField.setInput(ids); environmentField.setSelection(selection); } finally { --busy; } }); } private int busy = 0; private boolean isBusy() { return busy != 0; } private String[] collectEnvironments() { final List<String> ids = new ArrayList<>(); for (String envId : environments.getEnvironmentIds()) { if (environmentPredicate.evaluate(envId)) { ids.add(envId); } } for (CheckerEnvironmentInstance environmentInstance : instance.getEnvironments()) { final String envId = environmentInstance.getEnvironmentId(); if (environmentPredicate.evaluate(envId) && !ids.contains(envId)) { ids.add(envId); } } return ids.toArray(new String[ids.size()]); } /** * @param content */ private void createVersion(Composite parent) { SWTFactory.createLabel(parent, Messages.TclCheckerInstanceDialog_Version, 1); versionField = SWTFactory.createCombo(parent, SWT.BORDER | SWT.READ_ONLY, 1, new String[] { CheckerVersion.VERSION4.getDescription(), CheckerVersion.VERSION5.getDescription() }); } private void createPath(Composite parent) { SWTFactory.createLabel(parent, Messages.TclCheckerInstanceDialog_ExecutablePath, 1); pathField = SWTFactory.createText(parent, SWT.BORDER, 1, Util.EMPTY_STRING, GridData.FILL_HORIZONTAL); ((GridData) pathField.getLayoutData()).widthHint = new PixelConverter(parent).convertWidthInCharsToPixels(64); pathField.addModifyListener(e -> { if (environmentInstance != null) { environmentInstance.setExecutablePath(pathField.getText()); } validate(); }); Button browse = SWTFactory.createPushButton(parent, Messages.TclCheckerInstanceDialog_Browse); browse.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { final IEnvironment environment = getEnvironment(); if (environment != null) { final IEnvironmentUI ui = environment.getAdapter(IEnvironmentUI.class); final String path = ui.selectFile(getContext().getShell(), IEnvironmentUI.EXECUTABLE); if (path != null) { pathField.setText(path); if (environmentInstance != null) { environmentInstance.setExecutablePath(path); } validate(); } } } }); } private void createCommandLineOptions(Composite parent) { SWTFactory.createLabel(parent, Messages.TclCheckerInstanceDialog_CommandLineOptions, 1); cliField = SWTFactory.createText(parent, SWT.BORDER, 1, Util.EMPTY_STRING); } private void createPCXGroup(Composite parent) { Group pcxGroup = new Group(parent, SWT.NONE); pcxGroup.setText(Messages.TclChecker_pcxPath); GridData groupLayoutData = new GridData(GridData.FILL_BOTH); groupLayoutData.horizontalSpan = 3; pcxGroup.setLayoutData(groupLayoutData); pcxGroup.setLayout(new GridLayout(2, false)); noPCX = SWTFactory.createCheckButton(pcxGroup, Messages.TclCheckerInstanceDialog_DisablePCX, 2); noPCX.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (environmentInstance != null) { environmentInstance.setUsePcxFiles(noPCX.getSelection()); } updatePcxGroupEnablement(noPCX.getSelection(), pcxList.getSelection()); validate(); } }); pcxList = new ListViewer(pcxGroup, SWT.BORDER); pcxList.getList().setLayoutData(new GridData(GridData.FILL_BOTH)); pcxList.setContentProvider(new IStructuredContentProvider() { @Override public Object[] getElements(Object inputElement) { if (inputElement instanceof List) { return ((List<?>) inputElement).toArray(); } return new Object[0]; } @Override public void dispose() { } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); pcxList.setLabelProvider(new LabelProvider()); pcxList.addSelectionChangedListener( event -> updatePcxGroupEnablement(noPCX.getSelection(), event.getSelection())); Composite buttons = new Composite(pcxGroup, SWT.NONE); RowLayout row = new RowLayout(SWT.VERTICAL); row.fill = true; buttons.setLayout(row); pcxAdd = SWTFactory.createPushButtonNoLayoutData(buttons, Messages.TclCheckerInstanceDialog_pcxAdd); pcxAdd.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (environmentInstance == null) { return; } final PathDialog pathDialog = new PathDialog(pcxAdd.getShell(), getEnvironment()); pathDialog.setTitle(Messages.TclCheckerInstanceDialog_pcxAddTitle); if (pathDialog.open() == Window.OK) { final String path = pathDialog.getPath(); if (path != null) { environmentInstance.getPcxFileFolders().add(path); pcxList.add(path); validate(); } } } }); pcxBrowse = SWTFactory.createPushButtonNoLayoutData(buttons, Messages.TclCheckerInstanceDialog_pcxBrowse); pcxBrowse.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (environmentInstance == null) { return; } final IEnvironment environment = getEnvironment(); if (environment != null) { final IEnvironmentUI ui = environment.getAdapter(IEnvironmentUI.class); final String path = ui.selectFolder(pcxBrowse.getShell()); if (path != null) { environmentInstance.getPcxFileFolders().add(path); pcxList.add(path); validate(); } } } }); pcxRemove = SWTFactory.createPushButtonNoLayoutData(buttons, Messages.TclCheckerInstanceDialog_pcxRemove); pcxRemove.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (environmentInstance == null) { return; } final ISelection selection = pcxList.getSelection(); if (selection instanceof IStructuredSelection) { for (Iterator<?> i = ((IStructuredSelection) selection).iterator(); i.hasNext();) { final String path = (String) i.next(); environmentInstance.getPcxFileFolders().remove(path); pcxList.remove(path); validate(); } } } }); } private void updatePcxGroupEnablement(boolean noPCX, ISelection selection) { pcxAdd.setEnabled(!noPCX); pcxBrowse.setEnabled(!noPCX); pcxRemove.setEnabled(!noPCX && !selection.isEmpty()); pcxList.getControl().setEnabled(!noPCX); } private void refreshEnvironmentFields() { pathField.setEnabled(environmentInstance != null); pcxList.getList().setEnabled(environmentInstance != null); noPCX.setEnabled(environmentInstance != null); if (environmentInstance != null) { pathField.setText(StrUtils.toString(environmentInstance.getExecutablePath())); pcxList.setInput(environmentInstance.getPcxFileFolders()); noPCX.setSelection(!environmentInstance.isUsePcxFiles()); updatePcxGroupEnablement(!environmentInstance.isUsePcxFiles(), pcxList.getSelection()); } else { updatePcxGroupEnablement(true, StructuredSelection.EMPTY); } } protected IEnvironment getEnvironment() { final ISelection selection = environmentField.getSelection(); if (selection != null && !selection.isEmpty() && selection instanceof IStructuredSelection) { final IStructuredSelection ss = (IStructuredSelection) selection; if (ss.size() == 1) { return environments.get((String) ss.getFirstElement()); } } return null; } @Override public void initControls() { nameField.setText(StrUtils.toString(instance.getName())); versionField.select(CheckerVersion.VALUES.indexOf(instance.getVersion())); cliField.setText(StrUtils.toString(instance.getCommandLineOptions())); ++busy; try { final String[] ids = collectEnvironments(); environmentField.setInput(ids); if (ids.length != 0) { environmentField.setSelection(new StructuredSelection(ids[0])); environmentInstance = instance.getEnvironment(ids[0]); } else { environmentField.setSelection(StructuredSelection.EMPTY); environmentInstance = null; } } finally { --busy; } refreshEnvironmentFields(); } @Override public IStatus isValid(Object hint) { final String name = nameField.getText(); if (name == null || name.trim().length() == 0) { return new StatusInfo(IStatus.ERROR, Messages.TclCheckerInstanceBlock_errorEmptyValidatorName); } if (instance.getValidatorEnvironments().isEmpty()) { return new StatusInfo(IStatus.ERROR, Messages.TclCheckerInstanceBlock_ErrorNoEnvironments); } final Map<ValidatorEnvironmentInstance, IStatus> environmentStatus = new HashMap<>(); int correctEnvironments = 0; for (ValidatorEnvironmentInstance eInstance : instance.getValidatorEnvironments()) { final IStatus status = validateEnvironment(eInstance); if (status != null) { environmentStatus.put(eInstance, status); } else { ++correctEnvironments; } } if (correctEnvironments == 0) { return environmentStatus.get(environmentInstance); } return null; } private IStatus validateEnvironment(ValidatorEnvironmentInstance eInstance) { final String path = eInstance.getExecutablePath(); if (path == null || path.trim().length() == 0) { return new StatusInfo(IStatus.ERROR, Messages.TclCheckerInstanceBlock_ErrorPathNotSpecified); } final IEnvironment environment = environments.get(eInstance.getEnvironmentId()); if (environment != null && environment.isLocal()) { final Path pathObj = new Path(path); if (pathObj.isEmpty()) { return new StatusInfo(IStatus.ERROR, Messages.TclCheckerInstanceBlock_ErrorPathIsEmpty); } final IFileHandle file = PlatformFileUtils.findAbsoluteOrEclipseRelativeFile(environment, pathObj); if (file == null || !file.isFile()) { return new StatusInfo(IStatus.ERROR, NLS.bind(Messages.TclCheckerInstanceBlock_ErrorFileNotFound, path)); } } return null; } @Override public void saveValues() { instance.setName(nameField.getText()); int versionIndex = versionField.getSelectionIndex(); instance.setVersion(CheckerVersion.values()[versionIndex]); instance.setCommandLineOptions(cliField.getText()); } }