/******************************************************************************* * Copyright (c) 2007, 2015 Willink Transformations 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: * E.D.Willink - initial API and implementation *******************************************************************************/ package org.eclipse.ocl.examples.modelregistry.ui.properties; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.window.Window; import org.eclipse.ocl.examples.modelregistry.environment.FileHandle; import org.eclipse.ocl.examples.modelregistry.environment.ModelRegistryEnvironment; import org.eclipse.ocl.examples.modelregistry.model.Accessor; import org.eclipse.ocl.examples.modelregistry.model.AccessorRegistry; import org.eclipse.ocl.examples.modelregistry.model.FileHandleRegistry; import org.eclipse.ocl.examples.modelregistry.model.ModelNameAccessor; import org.eclipse.ocl.examples.modelregistry.model.ProjectRegistry; import org.eclipse.ocl.examples.modelregistry.model.Registration; import org.eclipse.ocl.examples.modelregistry.ui.help.ModelRegistryHelpIds; import org.eclipse.ocl.examples.modelregistry.ui.help.ModelRegistryHelper; import org.eclipse.ocl.examples.modelregistry.ui.icons.Icons; import org.eclipse.ocl.examples.modelregistry.ui.icons.ModelRegistryIcons; import org.eclipse.ocl.pivot.utilities.ClassUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; 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.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; /** */ public class ConfigurationBlock { public class RegistrationLabelComparator extends ViewerComparator { @Override public int compare(Viewer viewer, Object e1, Object e2) { return ((Registration<?>)e1).compareTo((Registration<?>)e2); } } private class RegistrationLabelProvider extends LabelProvider implements ITableLabelProvider, IColorProvider { public Color getBackground(Object element) { Registration<?> registration = (Registration<?>) element; if (!fileHandle.equals(registration.getFileHandle())) return shell.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); return null; } public Image getColumnImage(Object element, int columnIndex) { // TODO show a warning decoration (via Problems Page) if serialization factory does not exist // TODO invoke a builder on the .settings file to show if serialization factory does not exist if (columnIndex != 0) return null; Registration<?> registration = (Registration<?>) element; FileHandle lineHandle = registration.getFileHandle(); Enum<?> imageIcon = null; Enum<?> overlayIcon = null; Enum<?> underlayIcon = null; if (lineHandle.isFile() != null) imageIcon = ModelRegistryIcons.FILE; else if (lineHandle.isFolder() != null) imageIcon = ModelRegistryIcons.FOLDER; else if (lineHandle.isProject() != null) imageIcon = ModelRegistryIcons.PROJECT; try { File file = ModelRegistryEnvironment.getInstance().getFile(registration.getURI()); if ((file == null) || !file.exists()) overlayIcon = ModelRegistryIcons.WITH_WARNING; } catch (Exception e) { overlayIcon = ModelRegistryIcons.WITH_ERROR; } if (!isVisible(registration)) underlayIcon = ModelRegistryIcons.OCCLUDED; return Icons.getImage(imageIcon, overlayIcon, underlayIcon); } public String getColumnText(Object element, int columnIndex) { Registration<?> registration = (Registration<?>) element; switch (columnIndex) { case 0: return registration.getFileHandle().getName(); case 1: return registration.getAccessorName(); case 2: return registration.getURIString(); case 3: return registration.getModelKindName(); default: return null; } } public Color getForeground(Object element) { return null; } @Override public Image getImage(Object element) { return null; } @Override public String getText(Object element) { return getColumnText(element, 1); } } /* private static class RegistrationSorter extends ViewerComparator { public int compare(Viewer viewer, Object e1, Object e2) { return getComparator().compare(((Registration<?>) e1).getAccessorName(), ((Registration<?>) e2).getAccessorName()); } } */ class TableContentProvider implements IStructuredContentProvider { public Object[] getElements(Object inputElement) { return editedRegistrationModel.toArray(); } public void dispose() {} public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} } protected final FileHandle fileHandle; // File handle of selected resource private final ProjectRegistry projectRegistry; private final List<Registration<?>> editedRegistrationModel = new ArrayList<Registration<?>>(); // Current state private final List<Registration<?>> uneditedRegistrationModel = new ArrayList<Registration<?>>(); // State on load/save/revert private String namespaceName; private Shell shell = null; // Set by createContent private Button addButton = null; private Button editButton = null; private Button removeButton = null; private TableViewer tableViewer = null; public ConfigurationBlock(FileHandle handle) { this.fileHandle = handle; namespaceName = ModelNameAccessor.NAMESPACE.getName(); projectRegistry = new ProjectRegistry(handle.getProjectHandle()); projectRegistry.loadModel(); loadEditModel(); } private boolean canEdit(List<Registration<?>> selectedElements) { return (selectedElements.size() == 1) && fileHandle.equals(selectedElements.get(0).getFileHandle()); } private boolean canRemove(List<Registration<?>> selectedElements) { for (Registration<?> selectedElement : selectedElements) if (!fileHandle.equals(selectedElement.getFileHandle())) return false; return true; } public Button createAddButton(Composite parent, int widthHint) { addButton = new Button(parent, SWT.PUSH); addButton.setText(PreferencesMessages.ModelRegistryConfigurationBlock_markers_tasks_add_button); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); Point minButtonSize = addButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); data.widthHint = Math.max(widthHint, minButtonSize.x); addButton.setLayoutData(data); addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { AccessorRegistry<?> accessorRegistry = getAccessorRegistry(); RegistrationDialog dialog = new RegistrationDialog(shell, accessorRegistry, null, editedRegistrationModel, fileHandle); if (dialog.open() == Window.OK) { editedRegistrationModel.add(dialog.getRegistration()); updateFromEditModel(); } } }); ModelRegistryHelper.setHelp(addButton, ModelRegistryHelpIds.PropertyPage.ADD); return addButton; } protected Control createContents(Composite parent) { shell = parent.getShell(); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 5; Composite inner = new Composite(parent, SWT.NULL); inner.setLayout(layout); inner.setFont(parent.getFont()); Table tableControl = createTableControl(inner); tableControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, layout.numColumns, 1)); updateFromEditModel(); // if (dialogList.getSize() > 0) { // dialogList.selectFirstElement(); // } else { // dialogList.enableButton(IDX_EDIT, false); // } return inner; } public Button createEditButton(Composite parent, int widthHint) { editButton = new Button(parent, SWT.PUSH); editButton.setText(PreferencesMessages.ModelRegistryConfigurationBlock_markers_tasks_edit_button); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); Point minButtonSize = editButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); data.widthHint = Math.max(widthHint, minButtonSize.x); editButton.setLayoutData(data); editButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { List<Registration<?>> selection = getSelectedRegistrations(); if (selection.size() > 0) { Registration<?> edited = selection.get(0); AccessorRegistry<?> accessorRegistry = getAccessorRegistry(); RegistrationDialog dialog = new RegistrationDialog(shell, accessorRegistry, edited, editedRegistrationModel, fileHandle); if (dialog.open() == Window.OK) { editedRegistrationModel.set(editedRegistrationModel.indexOf(edited), dialog.getRegistration()); updateFromEditModel(); } } } }); ModelRegistryHelper.setHelp(editButton, ModelRegistryHelpIds.PropertyPage.EDIT); return editButton; // FIXME editing a registration from .xml to .emof doesn't replace } public Button createRemoveButton(Composite parent, int widthHint) { removeButton = new Button(parent, SWT.PUSH); removeButton.setText(PreferencesMessages.ModelRegistryConfigurationBlock_markers_tasks_remove_button); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); Point minButtonSize = removeButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); data.widthHint = Math.max(widthHint, minButtonSize.x); removeButton.setLayoutData(data); removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { List<Registration<?>> selection = getSelectedRegistrations(); editedRegistrationModel.removeAll(selection); updateFromEditModel(); } }); ModelRegistryHelper.setHelp(removeButton, ModelRegistryHelpIds.PropertyPage.REMOVE); return removeButton; } protected Table createTableControl(Composite inner) { tableViewer = new TableViewer(inner); tableViewer.setContentProvider(new TableContentProvider()); tableViewer.setLabelProvider(new RegistrationLabelProvider()); tableViewer.setComparator(new RegistrationLabelComparator()); Table tableControl = tableViewer.getTable(); String[] columnsHeaders= new String[] { PreferencesMessages.ModelRegistryConfigurationBlock_container_column, PreferencesMessages.ModelRegistryConfigurationBlock_accessor_name_column, PreferencesMessages.ModelRegistryConfigurationBlock_platform_resource_column, PreferencesMessages.ModelRegistryConfigurationBlock_serialization_column }; int[] columnWidths = { 100, 85, 400, 40 }; // FIXME do some pixel conversion for (int i = 0; i < columnsHeaders.length; i++) { TableColumn column = new TableColumn(tableControl, SWT.NONE); column.setText(columnsHeaders[i]); column.setWidth(columnWidths[i]); } tableControl.setHeaderVisible(true); tableControl.setLinesVisible(true); tableControl.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateStatus(); } }); ModelRegistryHelper.setHelp(tableControl, ModelRegistryHelpIds.PropertyPage.TABLE); return tableControl; } public void dispose() {} public String getNamespaceName() { return namespaceName; } private AccessorRegistry<?> getAccessorRegistry() { if (namespaceName == null) return null; FileHandleRegistry fileHandleRegistry = projectRegistry.getOrCreate(fileHandle); if (fileHandleRegistry == null) return null; AccessorRegistry<?> accessorRegistry = fileHandleRegistry.getOrCreate(namespaceName); return accessorRegistry; } private List<Registration<?>> getSelectedRegistrations() { ISelection selection = tableViewer.getSelection(); if ((selection == null) || !(selection instanceof IStructuredSelection)) return Collections.emptyList(); return ClassUtil.asClassUnchecked(((IStructuredSelection)selection).toList(), (List<Registration<?>>)null); } public boolean isDirty() { if (editedRegistrationModel.size() != uneditedRegistrationModel.size()) return true; int iMax = editedRegistrationModel.size(); for (int i = 0; i < iMax; i++) { Registration<?> editedRegistration = editedRegistrationModel.get(i); Registration<?> uneditedRegistration = uneditedRegistrationModel.get(i); if (!editedRegistration.equals(uneditedRegistration)) return true; } return false; } private boolean isVisible(Registration<?> candidateRegistration) { // int candidateDepth = candidateRegistration.getFileHandleRegistry().getDepth(); Accessor<?> candidateAccessor = candidateRegistration.getAccessor(); Registration<?> visibleRegistration = null; int visibleDepth = -1; int iMax = editedRegistrationModel.size(); for (int i = 0; i < iMax; i++) { Registration<?> editedRegistration = editedRegistrationModel.get(i); if (editedRegistration.getAccessor().equals(candidateAccessor)) { int editedDepth = editedRegistration.getFileHandleRegistry().getDepth(); if (editedDepth >= visibleDepth) { visibleRegistration = editedRegistration; visibleDepth = editedDepth; } } } return visibleRegistration == candidateRegistration; } private void loadEditModel() { editedRegistrationModel.clear(); if (namespaceName != null) { for (FileHandle fileHandleAncestor = fileHandle; fileHandleAncestor != null; fileHandleAncestor = fileHandleAncestor.getParentFileHandle()) { FileHandleRegistry fileHandleRegistry = projectRegistry.get(fileHandleAncestor); if (fileHandleRegistry != null) { AccessorRegistry<?> accessorRegistry = fileHandleRegistry.getOrCreate(namespaceName); if (accessorRegistry != null) { Collection<? extends Registration<?>> fileHandleRegistrations = accessorRegistry.getRegistrations(); if (fileHandleRegistrations != null) editedRegistrationModel.addAll(fileHandleRegistrations); } } } } uneditedRegistrationModel.clear(); uneditedRegistrationModel.addAll(editedRegistrationModel); } public boolean performApply() { return saveEditModel(); } public void performDefaults() { performRevert(); } public boolean performOk() { return saveEditModel(); } public void performRevert() { editedRegistrationModel.clear(); editedRegistrationModel.addAll(uneditedRegistrationModel); updateFromEditModel(); } private boolean saveEditModel() { List<Registration<?>> newRegistrations = new ArrayList<Registration<?>>(editedRegistrationModel); List<Registration<?>> obsoleteRegistrations = new ArrayList<Registration<?>>(uneditedRegistrationModel); for (Registration<?> registration : editedRegistrationModel) { if (uneditedRegistrationModel.contains(registration)) { newRegistrations.remove(registration); obsoleteRegistrations.remove(registration); } } for (Registration<?> obsoleteRegistration : obsoleteRegistrations) if (projectRegistry.remove(obsoleteRegistration) == null) ModelRegistryEnvironment.logError("Failed to remove registration ' " + obsoleteRegistration + "'", null); for (Registration<?> newRegistration : newRegistrations) { Registration<?> displacedRegistration = projectRegistry.add(newRegistration); if (displacedRegistration != null) ModelRegistryEnvironment.logError("Displaced '" + displacedRegistration + "' when adding '" + newRegistration + "'", null); } if (!projectRegistry.saveModel()) return false; uneditedRegistrationModel.clear(); uneditedRegistrationModel.addAll(editedRegistrationModel); return true; } public boolean setNamespaceName(String namespaceName) { if (!this.namespaceName.equals(namespaceName)) { if (isDirty()) { if (!MessageDialog.openConfirm(shell, "Save Changes?", "The '" + namespaceName + "' accessor has unsaved changes. Do you wish to save them?")) return false; saveEditModel(); } this.namespaceName = namespaceName; loadEditModel(); updateFromEditModel(); } return true; } public void setEnabled(boolean isEnabled) { tableViewer.getTable().setEnabled(isEnabled); addButton.setEnabled(isEnabled); editButton.setEnabled(isEnabled); removeButton.setEnabled(isEnabled); } private void updateFromEditModel() { tableViewer.setInput(editedRegistrationModel); updateStatus(); } protected void updateStatus() { List<Registration<?>> selectedElements = getSelectedRegistrations(); if (editButton != null) editButton.setEnabled(canEdit(selectedElements)); if (removeButton != null) removeButton.setEnabled(canRemove(selectedElements)); } }