blob: d23694639a7cb557db5cbd55deff56c2608b1945 [file] [log] [blame]
/*
* Copyright (c) 2014-2017 Eike Stepper (Loehne, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.oomph.setup.ui.recorder;
import org.eclipse.oomph.base.provider.BaseEditUtil;
import org.eclipse.oomph.internal.ui.AbstractPreferencePage;
import org.eclipse.oomph.setup.Installation;
import org.eclipse.oomph.setup.Product;
import org.eclipse.oomph.setup.Project;
import org.eclipse.oomph.setup.Scope;
import org.eclipse.oomph.setup.Stream;
import org.eclipse.oomph.setup.Workspace;
import org.eclipse.oomph.setup.internal.core.SetupContext;
import org.eclipse.oomph.setup.internal.core.util.SetupCoreUtil;
import org.eclipse.oomph.setup.ui.SetupEditorSupport;
import org.eclipse.oomph.setup.ui.SetupLabelProvider;
import org.eclipse.oomph.setup.ui.SetupUIPlugin;
import org.eclipse.oomph.setup.ui.synchronizer.SynchronizerManager;
import org.eclipse.oomph.ui.SearchField;
import org.eclipse.oomph.ui.SearchField.FilterHandler;
import org.eclipse.oomph.ui.ToolButton;
import org.eclipse.oomph.ui.UIUtil;
import org.eclipse.oomph.util.ObjectUtil;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceNode;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.nebula.widgets.tablecombo.TableCombo;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Label;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class RecorderPreferencePage extends AbstractPreferencePage
{
private static RecorderPreferencePage instance;
private final URIConverter uriConverter = SetupCoreUtil.createResourceSet().getURIConverter();
private RecorderTransaction transaction;
private Button enableButton;
private TableCombo targetCombo;
private ToolButton editButton;
private Label policiesLabel;
private SearchField policiesFilter;
private RecorderPoliciesComposite policiesComposite;
private Button initializePreferencesButton;
private Job openTransactionJob;
public RecorderPreferencePage()
{
instance = this;
}
@Override
public void dispose()
{
if (transaction != null)
{
closeRecorderTransaction();
}
instance = null;
super.dispose();
}
@Override
protected Control doCreateContents(Composite parent)
{
if (RecorderManager.INSTANCE.hasTemporaryRecorderTarget())
{
Label label = new Label(parent, SWT.NONE);
label.setText("The preference recorder settings are unavailable while recording into the selected file.");
return label;
}
int columns = 3;
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(UIUtil.createGridLayout(columns));
enableButton = new Button(composite, SWT.CHECK);
enableButton.setText("Record into:");
enableButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
boolean enableRecorder = enableButton.getSelection();
RecorderManager.INSTANCE.setRecorderEnabled(enableRecorder);
if (!enableRecorder)
{
policiesFilter.getFilterControl().setText("");
}
updateEnablement();
RecorderManager.updateRecorderToggleButton();
if (enableRecorder && SynchronizerManager.Availability.AVAILABLE)
{
boolean firstTime = SynchronizerManager.INSTANCE.offerFirstTimeConnect(getShell());
RecorderManager.INSTANCE.startEarlySynchronization(firstTime);
}
}
});
targetCombo = new TableCombo(composite, SWT.BORDER | SWT.READ_ONLY);
targetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
targetCombo.defineColumns(2);
targetCombo.setToolTipText("Select the recorder target file");
targetCombo.getTable().addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
if (e.item instanceof TableItem)
{
TableItem item = (TableItem)e.item;
URI uri = (URI)item.getData();
URI oldURI = RecorderManager.INSTANCE.setRecorderTarget(uri);
if (oldURI != null)
{
if (transaction != null)
{
int dirtyPolicies = transaction.getPolicies(false).size();
if (dirtyPolicies != 0)
{
if (MessageDialog.openQuestion(getShell(), "Changed Recorder Policies",
"Do you want to save the changed policies before you change the recorder target?"))
{
transaction.commit();
}
}
closeRecorderTransaction();
}
openRecorderTransaction(null);
}
}
}
});
ComposedAdapterFactory adapterFactory = BaseEditUtil.createAdapterFactory();
SetupContext setupContext = SetupContext.getSelf();
Set<Scope> targets = new HashSet<Scope>();
addTarget(adapterFactory, targets, setupContext.getUser());
Installation installation = setupContext.getInstallation();
addTarget(adapterFactory, targets, installation);
Workspace workspace = setupContext.getWorkspace();
addTarget(adapterFactory, targets, workspace);
if (installation != null)
{
addTarget(adapterFactory, targets, installation.getProductVersion());
}
if (workspace != null)
{
for (Stream stream : workspace.getStreams())
{
addTarget(adapterFactory, targets, stream);
}
}
URI uri = RecorderManager.INSTANCE.getRecorderTarget();
selectRecorderTarget(uri);
adapterFactory.dispose();
editButton = new ToolButton(composite, 0, SetupUIPlugin.INSTANCE.getSWTImage("edit.gif"), false);
editButton.setToolTipText("Open the recorder target file");
editButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
if (page != null)
{
SetupEditorSupport.getEditor(page, RecorderManager.INSTANCE.getRecorderTarget(), true);
Map<String, Boolean> policies = null;
if (transaction != null)
{
policies = transaction.getPolicies(false);
closeRecorderTransaction();
}
openRecorderTransaction(policies);
updateEnablement();
}
}
});
Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
separator.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, columns, 1));
policiesLabel = new Label(composite, SWT.NONE);
policiesLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, columns, 1));
policiesLabel.setText("Check the preferences to record and uncheck those to ignore:");
FilterHandler filterHandler = new FilterHandler()
{
public void handleFilter(String filter)
{
ViewerFilter viewerFilter = null;
if (filter.length() != 0)
{
final String subString = filter.toLowerCase();
viewerFilter = new ViewerFilter()
{
@Override
public boolean select(Viewer viewer, Object parentElement, Object element)
{
return ((String)element).toLowerCase().contains(subString);
}
};
}
policiesComposite.setFilter(viewerFilter);
policiesComposite.selectFirstPolicy();
}
};
policiesFilter = new SearchField(composite, filterHandler)
{
@Override
protected void finishFilter()
{
policiesComposite.setFocus();
policiesComposite.selectFirstPolicy();
}
};
policiesFilter.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, columns, 1));
policiesComposite = new RecorderPoliciesComposite(composite, SWT.BORDER | SWT.FULL_SELECTION, true);
policiesComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, columns, 1));
policiesComposite.addCheckStateListener(new ICheckStateListener()
{
public void checkStateChanged(CheckStateChangedEvent event)
{
updateEnablement();
}
});
updateEnablement();
openRecorderTransaction(null);
return composite;
}
@Override
public void createControl(Composite parent)
{
super.createControl(parent);
((GridLayout)initializePreferencesButton.getParent().getLayout()).numColumns += 1;
}
@Override
protected void contributeButtons(Composite parent)
{
initializePreferencesButton = new Button(parent, SWT.PUSH);
initializePreferencesButton.setText("Initialize...");
int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
Dialog.applyDialogFont(initializePreferencesButton);
Point minButtonSize = initializePreferencesButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
data.widthHint = Math.max(widthHint, minButtonSize.x);
initializePreferencesButton.setLayoutData(data);
final PreferenceManager preferenceManager = PlatformUI.getWorkbench().getPreferenceManager();
initializePreferencesButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
new PreferenceInitializationDialog((PreferenceDialog)getContainer(), preferenceManager).open();
}
});
Set<String> preferencePages = RecorderManager.INSTANCE.getInitializedPreferencePages();
@SuppressWarnings("all")
List<IPreferenceNode> preferenceNodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER);
for (IPreferenceNode element : preferenceNodes)
{
String id = element.getId();
if (preferencePages.contains(id))
{
initializePreferencesButton.setEnabled(false);
break;
}
}
}
private void openRecorderTransaction(final Map<String, Boolean> policies)
{
if (openTransactionJob == null)
{
openTransactionJob = new Job("Open recorder transaction")
{
@Override
protected IStatus run(final IProgressMonitor monitor)
{
if (!monitor.isCanceled())
{
final RecorderTransaction transaction = RecorderTransaction.open();
transaction.setPolicies(policies);
if (!monitor.isCanceled())
{
UIUtil.syncExec(policiesComposite, new Runnable()
{
public void run()
{
if (!monitor.isCanceled())
{
updateEnablement();
policiesComposite.setRecorderTransaction(transaction);
RecorderPreferencePage.this.transaction = transaction;
}
}
});
}
}
return Status.OK_STATUS;
}
};
openTransactionJob.setSystem(true);
}
openTransactionJob.cancel();
openTransactionJob.schedule();
}
private void closeRecorderTransaction()
{
transaction.close();
transaction = null;
}
@Override
protected void performDefaults()
{
transaction.resetPolicies();
policiesComposite.setRecorderTransaction(transaction);
super.performDefaults();
}
@Override
protected void performApply()
{
super.performApply();
updateEnablement();
}
@Override
public boolean performOk()
{
if (transaction != null)
{
transaction.commit();
closeRecorderTransaction();
}
return super.performOk();
}
private boolean needsApply()
{
return transaction != null && transaction.isDirty();
}
private void selectRecorderTarget(URI uri)
{
int i = 0;
for (TableItem item : targetCombo.getTable().getItems())
{
URI itemURI = (URI)item.getData();
if (ObjectUtil.equals(itemURI, uri))
{
targetCombo.select(i);
return;
}
++i;
}
}
private boolean addTarget(ComposedAdapterFactory adapterFactory, Set<Scope> targets, Scope target)
{
if (target != null && targets.add(target))
{
URI uri = EcoreUtil.getURI(target);
if (uri != null)
{
Map<?, ?> options = Collections.singletonMap(URIConverter.OPTION_REQUESTED_ATTRIBUTES, Collections.singleton(URIConverter.ATTRIBUTE_READ_ONLY));
Map<String, ?> attributes = uriConverter.getAttributes(uri.trimFragment(), options);
boolean writable = !Boolean.TRUE.equals(attributes.get(URIConverter.ATTRIBUTE_READ_ONLY));
if (writable)
{
Scope parentScope = target.getParentScope();
if (parentScope instanceof Product || parentScope instanceof Project)
{
addTarget(adapterFactory, targets, parentScope);
}
String location = uri.trimFragment().toString();
ItemProviderAdapter itemProvider = (ItemProviderAdapter)adapterFactory.adapt(target, IItemLabelProvider.class);
TableItem item = new TableItem(targetCombo.getTable(), SWT.NONE);
item.setData(uri);
item.setImage(0, SetupUIPlugin.INSTANCE.getSWTImage(SetupLabelProvider.getImageDescriptor(itemProvider, target)));
item.setText(0, SetupLabelProvider.getText(itemProvider, target));
item.setText(1, location);
return true;
}
}
}
return false;
}
static void updateEnablement()
{
if (instance != null)
{
boolean recorderEnabled = RecorderManager.INSTANCE.isRecorderEnabled();
if (instance.enableButton != null)
{
instance.enableButton.setSelection(recorderEnabled);
instance.targetCombo.setEnabled(recorderEnabled);
instance.editButton.setEnabled(recorderEnabled && (instance.transaction == null || instance.transaction.getEditor() == null));
instance.policiesLabel.setEnabled(recorderEnabled);
instance.policiesFilter.setEnabled(recorderEnabled);
instance.policiesComposite.setEnabled(recorderEnabled);
}
Button applyButton = instance.getApplyButton();
if (applyButton != null)
{
boolean needsApply = instance.needsApply();
applyButton.setEnabled(needsApply);
}
Button defaultsButton = instance.getDefaultsButton();
if (defaultsButton != null)
{
defaultsButton.setEnabled(recorderEnabled);
}
}
}
}