/* * 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.project.editor.variables; import java.util.Arrays; import java.util.List; import java.util.function.Supplier; import javax.inject.Inject; import org.eclipse.e4.core.di.annotations.Optional; import org.eclipse.e4.tools.services.IDirtyProviderService; import org.eclipse.e4.ui.di.UIEventTopic; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.RowExposingTableViewer; import org.eclipse.jface.viewers.ViewerColumnsFactory; import org.eclipse.jface.viewers.ViewersConfigurator; import org.eclipse.jface.window.ToolTip; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.forms.widgets.Section; import org.rf.ide.core.project.RobotProjectConfig; import org.rf.ide.core.project.RobotProjectConfig.ReferencedVariableFile; import org.robotframework.ide.eclipse.main.plugin.RedPlugin; import org.robotframework.ide.eclipse.main.plugin.project.RobotProjectConfigEvents; import org.robotframework.ide.eclipse.main.plugin.project.editor.Environments; import org.robotframework.ide.eclipse.main.plugin.project.editor.RedProjectEditorInput; import org.robotframework.ide.eclipse.main.plugin.project.editor.variables.VariableFilesPathEditingSupport.VariableFileCreator; import org.robotframework.ide.eclipse.main.plugin.tableeditor.CellsActivationStrategy; import org.robotframework.ide.eclipse.main.plugin.tableeditor.CellsActivationStrategy.RowTabbingStrategy; import org.robotframework.ide.eclipse.main.plugin.tableeditor.HeaderFilterMatchesCollection; import org.robotframework.ide.eclipse.main.plugin.tableeditor.ISectionFormFragment; import org.robotframework.red.forms.RedFormToolkit; import org.robotframework.red.viewers.ElementAddingToken; import org.robotframework.red.viewers.StructuredContentProvider; import org.robotframework.red.viewers.Viewers; /** * @author mmarzec */ class VariableFilesFormFragment implements ISectionFormFragment { private static final String CONTEXT_ID = "org.robotframework.ide.eclipse.redxmleditor.varfiles.context"; @Inject private IEditorSite site; @Inject private RedFormToolkit toolkit; @Inject private IDirtyProviderService dirtyProviderService; @Inject private RedProjectEditorInput editorInput; private RowExposingTableViewer viewer; ISelectionProvider getViewer() { return viewer; } @Override public void initialize(final Composite parent) { final Section section = createSection(parent); final Composite internalComposite = toolkit.createComposite(section); section.setClient(internalComposite); GridDataFactory.fillDefaults().grab(true, true).applyTo(internalComposite); GridLayoutFactory.fillDefaults().applyTo(internalComposite); createViewer(internalComposite); createColumns(); createContextMenu(); setInput(); } private Section createSection(final Composite parent) { final Section section = toolkit.createSection(parent, ExpandableComposite.EXPANDED | ExpandableComposite.TITLE_BAR | Section.DESCRIPTION); section.setText("Variable files"); section.setDescription("Specify global variables files. Variables from the files below will be " + "available for all suites within the project without importing the file using Variables setting."); GridDataFactory.fillDefaults().grab(true, true).applyTo(section); return section; } private void createViewer(final Composite parent) { viewer = new RowExposingTableViewer(parent, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); CellsActivationStrategy.addActivationStrategy(viewer, RowTabbingStrategy.MOVE_TO_NEXT); ColumnViewerToolTipSupport.enableFor(viewer, ToolTip.NO_RECREATE); GridDataFactory.fillDefaults().grab(true, true).indent(0, 10).applyTo(viewer.getTable()); viewer.setUseHashlookup(true); viewer.getTable().setEnabled(false); viewer.getTable().setLinesVisible(true); viewer.getTable().setHeaderVisible(true); viewer.setContentProvider(new VariableFilesContentProvider()); ViewersConfigurator.enableDeselectionPossibility(viewer); ViewersConfigurator.disableContextMenuOnHeader(viewer); Viewers.boundViewerWithContext(viewer, site, CONTEXT_ID); } private void createColumns() { final Supplier<ReferencedVariableFile> elementsCreator = new VariableFileCreator(viewer.getTable().getShell(), editorInput); createFileColumn(elementsCreator); final int numberOfColumns = calculateLongestArgumentsLength(); for (int i = 0; i < numberOfColumns; i++) { final String name = i == 0 ? "Arguments" : ""; final boolean isLast = i == (numberOfColumns - 1); createArgumentColumn(name, i, elementsCreator, isLast); } } private void createFileColumn(final Supplier<ReferencedVariableFile> creator) { ViewerColumnsFactory.newColumn("File").withWidth(300) .withMinWidth(100) .editingEnabledOnlyWhen(editorInput.isEditable()) .editingSupportedBy(new VariableFilesPathEditingSupport(viewer, creator)) .labelsProvidedBy(new VariableFilesLabelProvider(editorInput)) .createFor(viewer); } private int calculateLongestArgumentsLength() { int max = RedPlugin.getDefault().getPreferences().getMinimalNumberOfArgumentColumns(); final List<?> elements = (List<?>) viewer.getInput(); if (elements != null) { for (final Object element : elements) { final ReferencedVariableFile varFile = (ReferencedVariableFile) element; if (varFile != null) { max = Math.max(max, varFile.getArguments().size()); } } } return max; } private void createArgumentColumn(final String name, final int index, final Supplier<ReferencedVariableFile> elementsCreator, final boolean shouldGrabAllTheSpace) { ViewerColumnsFactory.newColumn(name).withWidth(100) .shouldGrabAllTheSpaceLeft(shouldGrabAllTheSpace).withMinWidth(50) .editingEnabledOnlyWhen(editorInput.isEditable()) .editingSupportedBy(new VariableFileArgumentsEditingSupport(viewer, index, elementsCreator)) .labelsProvidedBy(new VariableFileArgumentsLabelProvider(index)) .createFor(viewer); } private void createContextMenu() { final String menuId = "org.robotframework.ide.eclipse.redxmleditor.variablefiles.contextMenu"; final MenuManager manager = new MenuManager("Red.xml file editor variable files context menu", menuId); final Table control = viewer.getTable(); final Menu menu = manager.createContextMenu(control); control.setMenu(menu); site.registerContextMenu(menuId, manager, viewer, false); } private void setInput() { final List<ReferencedVariableFile> files = editorInput.getProjectConfiguration().getReferencedVariableFiles(); viewer.setInput(files); } @Override public void setFocus() { viewer.getTable().setFocus(); } private void setDirty(final boolean isDirty) { dirtyProviderService.setDirtyState(isDirty); } @Override public HeaderFilterMatchesCollection collectMatches(final String filter) { return null; } @Inject @Optional private void whenEnvironmentLoadingStarted( @UIEventTopic(RobotProjectConfigEvents.ROBOT_CONFIG_ENV_LOADING_STARTED) final RobotProjectConfig config) { setInput(); viewer.getTable().setEnabled(false); } @Inject @Optional private void whenEnvironmentsWereLoaded( @UIEventTopic(RobotProjectConfigEvents.ROBOT_CONFIG_ENV_LOADED) final Environments envs) { viewer.getTable().setEnabled(editorInput.isEditable()); } @Inject @Optional private void whenVarFileDetailChanged( @UIEventTopic(RobotProjectConfigEvents.ROBOT_CONFIG_VAR_FILE_DETAIL_CHANGED) final ReferencedVariableFile varFile) { setDirty(true); viewer.refresh(); } @Inject @Optional private void whenVarFileChanged( @UIEventTopic(RobotProjectConfigEvents.ROBOT_CONFIG_VAR_FILE_STRUCTURE_CHANGED) final List<ReferencedVariableFile> varFiles) { setDirty(true); viewer.refresh(); } private class VariableFilesContentProvider extends StructuredContentProvider { @Override public Object[] getElements(final Object inputElement) { final Object[] elements = ((List<?>) inputElement).toArray(); if (editorInput.isEditable()) { final Object[] newElements = Arrays.copyOf(elements, elements.length + 1, Object[].class); newElements[elements.length] = new ElementAddingToken("variable file", true); return newElements; } else { return elements; } } } }