/******************************************************************************* * Copyright (c) 2014 Fraunhofer IWU 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: * Fraunhofer IWU - initial API and implementation *******************************************************************************/ package net.enilink.komma.edit.ui.wizards; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import net.enilink.komma.core.IReference; import net.enilink.komma.core.URI; import net.enilink.komma.core.URIs; import net.enilink.komma.edit.domain.IEditingDomain; import net.enilink.komma.edit.refactor.Change; import net.enilink.komma.edit.refactor.RefactoringProcessor; import net.enilink.komma.model.IObject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; 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.Text; import org.eclipse.ui.IWorkbench; public class RefactorRenameWizard extends Wizard { protected WizardPage configureRenamesPage; protected WizardPage showPreviewPage; protected Map<IObject, IReference> renameMap; protected Collection<Change> changes; protected Composite containerComposite; protected IWorkbench workbench; protected IEditingDomain domain; protected IStructuredSelection currentSelection; @Override public void createPageControls(Composite pageContainer) { super.createPageControls(pageContainer); containerComposite = pageContainer; } public RefactorRenameWizard(IEditingDomain domain, IWorkbench workbench, IStructuredSelection currentSelection) { this.domain = domain; this.workbench = workbench; this.currentSelection = currentSelection; this.renameMap = new LinkedHashMap<IObject, IReference>(); for (Object object : currentSelection.toArray()) { if (object instanceof IObject) { renameMap.put((IObject) object, null); } } setWindowTitle("Refactor - Rename content within models"); setNeedsProgressMonitor(true); createPages(); } static class TableLabelProvider extends ColumnLabelProvider { public static enum ColumnType { BEFORE, AFTER }; ColumnType column; public TableLabelProvider(ColumnType column) { this.column = column; } @Override public Image getImage(Object element) { return null; } @SuppressWarnings("rawtypes") @Override public String getText(Object element) { if (element instanceof Map.Entry) { Map.Entry entry = (Map.Entry) element; switch (column) { case BEFORE: return entry.getKey().toString(); case AFTER: IReference value = (IReference) entry.getValue(); return value != null ? value.toString() : null; default: return null; } } return null; } }; protected void createPages() { configureRenamesPage = new WizardPage("Configure the new URIs to use.") { @Override public void createControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new GridLayout()); // nested composite for "one namespace to rule them all" Composite nsComposite = new Composite(composite, SWT.NONE); GridLayout ncLayout = new GridLayout(2, false); ncLayout.marginHeight = 0; ncLayout.marginWidth = 0; nsComposite.setLayout(ncLayout); // toggle button for generic or individual renaming final Button useSameButton = new Button(nsComposite, SWT.CHECK); useSameButton.setSelection(false); useSameButton.setText("Move all elements into this namespace:"); // FIXME: add validation (URI) for text input field final Text namespace = new Text(nsComposite, SWT.BORDER); namespace.setLayoutData(new GridData(300, SWT.DEFAULT)); namespace.setEnabled(useSameButton.getSelection()); // the table viewer for the rename-mappings final TableViewer tableViewer = new TableViewer(composite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); tableViewer.getTable() .setEnabled(!useSameButton.getSelection()); tableViewer.getTable().setHeaderVisible(true); tableViewer.getTable().setLinesVisible(true); tableViewer.setContentProvider(ArrayContentProvider .getInstance()); TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.LEFT); column.getColumn().setText("Current URI"); column.getColumn().setWidth(300); column.setLabelProvider(new TableLabelProvider( TableLabelProvider.ColumnType.BEFORE)); column = new TableViewerColumn(tableViewer, SWT.LEFT); column.getColumn().setText("New URI"); column.getColumn().setWidth(300); column.setLabelProvider(new TableLabelProvider( TableLabelProvider.ColumnType.AFTER)); // FIXME: add validation (URI) for text input field final CellEditor cellEditor = new TextCellEditor( (Composite) tableViewer.getControl()); column.setEditingSupport(new EditingSupport(tableViewer) { @Override protected CellEditor getCellEditor(Object element) { return cellEditor; } @Override protected boolean canEdit(Object element) { return (element instanceof Map.Entry); } @SuppressWarnings("rawtypes") @Override protected Object getValue(Object element) { if (element instanceof Map.Entry) { IReference value = (IReference) ((Map.Entry) element) .getValue(); return value != null ? value.toString() : ""; } return ""; } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override protected void setValue(Object element, Object value) { if (element instanceof Map.Entry) { if (!(value instanceof IReference)) { if (value.toString().isEmpty()) { value = null; } else { value = URIs.createURI(value.toString()); } } ((Map.Entry) element).setValue(value); tableViewer.refresh(element); } setPageComplete(!renameMap.values().contains(null)); getContainer().updateButtons(); } }); // button selection toggles text input and table viewer states useSameButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { namespace.setEnabled(useSameButton.getSelection()); tableViewer.getTable().setEnabled( !useSameButton.getSelection()); } }); // leaving the text input sets the namespace on all elements namespace.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { URI namespaceURI = URIs.createURI(namespace.getText()); for (Map.Entry<IObject, IReference> entry : renameMap .entrySet()) { entry.setValue(namespaceURI.appendFragment(entry .getKey().getURI().fragment())); } tableViewer.refresh(); setPageComplete(true); getContainer().updateButtons(); } }); tableViewer.setInput(renameMap.entrySet()); setDescription("Set the new URIs for your selected elements."); setControl(composite); setPageComplete(false); } }; showPreviewPage = new RefactorPreviewPage("Preview") { @Override public Collection<Change> collectChanges() { changes = new RefactoringProcessor(domain) .createRenameChanges(renameMap); return changes; } }; } @Override public void addPages() { addPage(configureRenamesPage); addPage(showPreviewPage); } @Override public IWizardPage getPreviousPage(IWizardPage currentPage) { if (currentPage == showPreviewPage) { return configureRenamesPage; } return null; } @Override public IWizardPage getNextPage(IWizardPage currentPage) { if (currentPage == configureRenamesPage) { return showPreviewPage; } return null; } public boolean canFinish() { return showPreviewPage.isPageComplete() && getContainer().getCurrentPage() == showPreviewPage; } @Override public boolean performFinish() { // call RefactoringProcessor again to apply the confirmed changes try { getContainer().run(true, false, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { IStatus result = new RefactoringProcessor(domain) .applyChanges(changes, monitor, null); if (!result.isOK()) { if (result.getException() != null) { result.getException().printStackTrace(); } } } }); return true; } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return false; } }