/* * Copyright 2015 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.robotframework.ide.eclipse.main.plugin.tableeditor.settings.popup; import static com.google.common.collect.Lists.newArrayList; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StyledCellLabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.StyledString.Styler; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewersConfigurator; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.TextStyle; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.model.BaseWorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.robotframework.ide.eclipse.main.plugin.RedImages; import org.robotframework.ide.eclipse.main.plugin.RedTheme; import org.robotframework.ide.eclipse.main.plugin.model.RobotElement; import org.robotframework.ide.eclipse.main.plugin.model.RobotKeywordCall; import org.robotframework.ide.eclipse.main.plugin.model.RobotSetting; import org.robotframework.ide.eclipse.main.plugin.model.RobotSettingsSection; import org.robotframework.ide.eclipse.main.plugin.model.RobotSuiteFile; import org.robotframework.ide.eclipse.main.plugin.model.cmd.settings.CreateFreshSettingCommand; import org.robotframework.ide.eclipse.main.plugin.model.cmd.settings.DeleteSettingCommand; import org.robotframework.ide.eclipse.main.plugin.model.cmd.settings.SetSettingArgumentCommand; import org.robotframework.ide.eclipse.main.plugin.tableeditor.RobotEditorCommandsStack; import org.robotframework.ide.eclipse.main.plugin.tableeditor.settings.popup.Settings.ImportArguments; import org.robotframework.red.graphics.ImagesManager; import org.robotframework.red.viewers.Selections; public class ImportVariablesComposite { private static IProject currentProject; private final RobotEditorCommandsStack commandsStack; private final FormToolkit formToolkit; private final Shell shell; private final RobotSettingsSection settingsSection; private TableViewer variablesViewer; private ISelectionChangedListener selectionChangedListener; public ImportVariablesComposite(final RobotEditorCommandsStack commandsStack, final RobotSuiteFile fileModel, final FormToolkit formToolkit, final Shell shell) { this.commandsStack = commandsStack; this.formToolkit = formToolkit; this.shell = shell; currentProject = fileModel.getProject().getProject(); this.settingsSection = fileModel.findSection(RobotSettingsSection.class).get(); } public Composite createImportVariablesComposite(final Composite parent) { final Composite variablesComposite = formToolkit.createComposite(parent); GridLayoutFactory.fillDefaults() .numColumns(2) .margins(3, 3) .extendedMargins(0, 0, 0, 3) .applyTo(variablesComposite); final Label titleLabel = formToolkit.createLabel(variablesComposite, "Imported variables files:"); titleLabel.setFont(JFaceResources.getBannerFont()); titleLabel.setForeground(formToolkit.getColors().getColor(IFormColors.TITLE)); GridDataFactory.fillDefaults().grab(true, false).span(2, 1).hint(700, SWT.DEFAULT).applyTo(titleLabel); variablesViewer = new TableViewer(variablesComposite); variablesViewer.setContentProvider(new ImportVariablesContentProvider()); variablesViewer.setLabelProvider(new VariablesLabelProvider()); GridDataFactory.fillDefaults().grab(true, true).hint(220, 250).applyTo(variablesViewer.getControl()); final Composite addVariablesButtons = formToolkit.createComposite(variablesComposite); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(addVariablesButtons); GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.BEGINNING).applyTo(addVariablesButtons); final Button addVariableFromWorkspaceBtn = formToolkit.createButton(addVariablesButtons, "Add Variables", SWT.PUSH); GridDataFactory.fillDefaults().grab(false, true).applyTo(addVariableFromWorkspaceBtn); addVariableFromWorkspaceBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { final Shell newShell = new Shell(shell); final ElementTreeSelectionDialog dialog = createAddVariableSelectionDialog(newShell, true, null); if (dialog.open() == Window.OK) { final Object[] results = dialog.getResult(); if (results != null) { final List<String> variablesPaths = newArrayList(); for (int i = 0; i < results.length; i++) { final IResource resource = (IResource) results[i]; final String path = ImportSettingFilePathResolver.createResourceRelativePath(resource, currentProject); variablesPaths.add(path); } handleVariableAdd(variablesPaths); } } newShell.dispose(); } }); final Button addExternalVariablesBtn = formToolkit.createButton(addVariablesButtons, "Add External Variables", SWT.PUSH); addExternalVariablesBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { final Shell newShell = new Shell(shell); final FileDialog dialog = new FileDialog(newShell, SWT.OPEN); dialog.setFilterExtensions(new String[] { "*.py", "*.*" }); dialog.setFilterPath(currentProject.getLocation().toOSString()); final String chosenFilePath = dialog.open(); if (chosenFilePath != null) { handleVariableAdd(newArrayList(ImportSettingFilePathResolver.createFileRelativePath( new Path(chosenFilePath), currentProject.getProject().getLocation()).toPortableString())); } newShell.dispose(); } }); final Button editVariablesBtn = formToolkit.createButton(addVariablesButtons, "Edit File Path", SWT.PUSH); GridDataFactory.fillDefaults().indent(0, 10).applyTo(editVariablesBtn); editVariablesBtn.setEnabled(false); editVariablesBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { final Settings variables = (Settings) variablesViewer.getInput(); final ImportArguments variablesFile = Selections .getSingleElement((IStructuredSelection) variablesViewer.getSelection(), ImportArguments.class); final List<String> args = variablesFile.getArgs(); final Shell newShell = new Shell(shell); if (args != null && !args.isEmpty()) { final IPath path = new Path(args.get(0)); final IResource initialProjectSelection = currentProject.findMember(path); String filePath = null; if (initialProjectSelection == null) { final FileDialog dialog = new FileDialog(newShell, SWT.OPEN); dialog.setFilterExtensions(new String[] { "*.py", "*.*" }); final IPath initialExtSelection = ImportSettingFilePathResolver.createFileAbsolutePath(path, currentProject); dialog.setFilterPath(initialExtSelection.removeLastSegments(1).toOSString()); dialog.setFileName(initialExtSelection.lastSegment()); final String chosenFilePath = dialog.open(); if (chosenFilePath != null) { filePath = ImportSettingFilePathResolver.createFileRelativePath( new Path(chosenFilePath), currentProject.getLocation()) .toPortableString(); } } else { final ElementTreeSelectionDialog dialog = createAddVariableSelectionDialog(newShell, false, initialProjectSelection); if (dialog.open() == Window.OK) { final Object result = dialog.getFirstResult(); if (result != null) { final IResource resource = (IResource) result; filePath = ImportSettingFilePathResolver.createResourceRelativePath(resource, currentProject); } } } if (filePath != null) { handleVariablesPathEdit(variables, variablesFile, filePath); } } newShell.dispose(); } }); final Button editVariablesArgsBtn = formToolkit.createButton(addVariablesButtons, "Edit File Arguments", SWT.PUSH); GridDataFactory.fillDefaults().applyTo(editVariablesArgsBtn); editVariablesArgsBtn.setEnabled(false); editVariablesArgsBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { final Settings variables = (Settings) variablesViewer.getInput(); final ImportArguments variablesFile = Selections .getSingleElement((IStructuredSelection) variablesViewer.getSelection(), ImportArguments.class); if (!variablesFile.getArgs().isEmpty()) { final List<String> args = variablesFile.getArgs().subList(1, variablesFile.getArgs().size()); final Shell newShell = new Shell(shell); final ImportSettingFileArgumentsDialog dialog = new ImportSettingFileArgumentsDialog(newShell, args); if (dialog.open() == Window.OK) { final List<String> newArgs = dialog.getArguments(); handleVariablesArgsEdit(variables, variablesFile, newArgs); } newShell.dispose(); } } }); final Button removeVariablesBtn = formToolkit.createButton(addVariablesButtons, "Remove", SWT.PUSH); GridDataFactory.fillDefaults().applyTo(removeVariablesBtn); removeVariablesBtn.setEnabled(false); removeVariablesBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { final Settings variables = (Settings) variablesViewer.getInput(); final List<ImportArguments> paths = Selections .getElements((IStructuredSelection) variablesViewer.getSelection(), ImportArguments.class); handleVariableRemove(variables, paths); } }); createViewerSelectionListener(removeVariablesBtn, editVariablesBtn, editVariablesArgsBtn); ViewersConfigurator.enableDeselectionPossibility(variablesViewer); return variablesComposite; } public TableViewer getVariablesViewer() { return variablesViewer; } public ISelectionChangedListener getSelectionChangedListener() { return selectionChangedListener; } private ElementTreeSelectionDialog createAddVariableSelectionDialog(final Shell shell, final boolean allowMultiple, final IResource initialSelection) { final ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(shell, new WorkbenchLabelProvider(), new BaseWorkbenchContentProvider()); dialog.setAllowMultiple(allowMultiple); dialog.setTitle("Select variables file"); dialog.setMessage("Select the variables file to import:"); dialog.setInput(ResourcesPlugin.getWorkspace().getRoot()); if (initialSelection != null) { dialog.setInitialSelection(initialSelection); } return dialog; } private void handleVariableAdd(final List<String> paths) { final List<ImportArguments> currentVariables = ((Settings) variablesViewer.getInput()) .getImportedVariablesArguments(); for (final String newPathString : paths) { if (!newPathString.isEmpty()) { final ArrayList<String> args = newArrayList(newPathString); commandsStack.execute(new CreateFreshSettingCommand(settingsSection, "Variables", args)); currentVariables.add(new ImportArguments(args)); } } variablesViewer.refresh(); } private void handleVariableRemove(final Settings importedSettings, final List<ImportArguments> resourcesToRemove) { final List<RobotSetting> settingsToRemove = newArrayList(); final List<RobotKeywordCall> currentVariables = settingsSection.getVariablesSettings(); for (final RobotElement element : currentVariables) { final RobotSetting setting = (RobotSetting) element; final List<String> args = setting.getArguments(); if (!args.isEmpty()) { if (resourcesToRemove.contains(new ImportArguments(args))) { settingsToRemove.add(setting); } } } importedSettings.getImportedVariablesArguments().removeAll(resourcesToRemove); commandsStack.execute(new DeleteSettingCommand(settingsToRemove)); variablesViewer.refresh(); } private void handleVariablesPathEdit(final Settings importedSettings, final ImportArguments variablesFile, final String newPath) { final List<RobotKeywordCall> currentVariables = settingsSection.getVariablesSettings(); for (final RobotElement element : currentVariables) { final RobotSetting setting = (RobotSetting) element; final List<String> args = setting.getArguments(); if (!args.isEmpty() && args.equals(variablesFile.getArgs())) { args.set(0, newPath); commandsStack.execute(new SetSettingArgumentCommand(setting, 0, newPath)); variablesFile.setArgs(args); break; } } variablesViewer.refresh(); } private void handleVariablesArgsEdit(final Settings importedSettings, final ImportArguments variablesFile, final List<String> newArgs) { final List<RobotKeywordCall> currentVariables = settingsSection.getVariablesSettings(); for (final RobotElement element : currentVariables) { final RobotSetting setting = (RobotSetting) element; final List<String> args = setting.getArguments(); if (!args.isEmpty() && args.equals(variablesFile.getArgs())) { final List<String> newVariablesArguments = newArrayList(args.get(0)); newVariablesArguments.addAll(newArgs); for (int i = 0; i < newArgs.size(); i++) { commandsStack.execute(new SetSettingArgumentCommand(setting, i + 1, newArgs.get(i))); // set arg after variable file path } variablesFile.setArgs(newVariablesArguments); break; } } variablesViewer.refresh(); } private void createViewerSelectionListener(final Button removeBtn, final Button editPathBtn, final Button editArgsBtn) { selectionChangedListener = new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final boolean isSettingSelected = variablesViewer.getTable().getSelectionCount() == 1; removeBtn.setEnabled(isSettingSelected); editPathBtn.setEnabled(isSettingSelected); editArgsBtn.setEnabled(isSettingSelected); } }; variablesViewer.addSelectionChangedListener(selectionChangedListener); } protected void setInitialSelection(final RobotSetting initialSetting) { final ImportArguments selectedImport = new ImportArguments( initialSetting.getArguments()); variablesViewer.setSelection(new StructuredSelection(selectedImport)); } private static class VariablesLabelProvider extends StyledCellLabelProvider { @Override public void update(final ViewerCell cell) { final StyledString label = getStyledText(cell.getElement()); cell.setText(label.getString()); cell.setStyleRanges(label.getStyleRanges()); cell.setImage(getImage(cell.getElement())); super.update(cell); } public Image getImage(final Object element) { return ImagesManager.getImage(RedImages.getRobotScalarVariableImage()); } public StyledString getStyledText(final Object element) { final ImportArguments importedVariable = (ImportArguments) element; final List<String> args = importedVariable.getArgs(); final StyledString text = new StyledString(""); if (args != null && !args.isEmpty()) { final IPath path = new Path(args.get(0)); final String parentPath = path.segmentCount() > 1 ? path.removeLastSegments(1).toString() : currentProject.getName(); final StringBuilder fileArgs = new StringBuilder(""); for (int i = 1; i < args.size(); i++) { fileArgs.append(":" + args.get(i)); } if(path.lastSegment() != null) { text.append(path.lastSegment()); } text.append(fileArgs.toString() + " - " + parentPath, new Styler() { @Override public void applyStyles(final TextStyle textStyle) { textStyle.foreground = RedTheme.getEclipseDecorationColor(); } }); } return text; } } private static class ImportVariablesContentProvider implements IStructuredContentProvider { @Override public void dispose() { // nothing to do } @Override public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) { // nothing to do } @Override public Object[] getElements(final Object inputElement) { final List<ImportArguments> variables = ((Settings) inputElement).getImportedVariablesArguments(); // Collections.sort(variables, new Comparator<ImportArguments>() { // // @Override // public int compare(final ImportArguments spec1, final ImportArguments spec2) { // return spec1.compareTo(spec2); // } // }); return variables.toArray(); } } }