| /* |
| * 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); |
| } |
| } |
| } |
| } |