blob: dcbf788f1f8dc8a302d37725789f775cfc99de76 [file] [log] [blame]
/*
* Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) 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:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.oomph.setup.ui.recorder;
import org.eclipse.oomph.preferences.PreferencesFactory;
import org.eclipse.oomph.preferences.util.PreferencesRecorder;
import org.eclipse.oomph.setup.User;
import org.eclipse.oomph.setup.internal.core.SetupContext;
import org.eclipse.oomph.setup.internal.core.util.SetupCoreUtil;
import org.eclipse.oomph.setup.ui.SetupUIPlugin;
import org.eclipse.oomph.ui.UIUtil;
import org.eclipse.oomph.util.StringUtil;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.ResourceSet;
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.preference.IPersistentPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
/**
* @author Eike Stepper
*/
public final class RecorderManager
{
public static final RecorderManager INSTANCE = new RecorderManager();
private static final IPersistentPreferenceStore SETUP_UI_PREFERENCES = (IPersistentPreferenceStore)SetupUIPlugin.INSTANCE.getPreferenceStore();
private static ToolItem toolItem;
private final DisplayListener displayListener = new DisplayListener();
private Display display;
private PreferencesRecorder recorder;
private RecorderManager()
{
}
public boolean isRecorderEnabled()
{
String value = SETUP_UI_PREFERENCES.getString(SetupUIPlugin.PREF_ENABLE_PREFERENCE_RECORDER);
if (StringUtil.isEmpty(value))
{
ResourceSet resourceSet = SetupCoreUtil.createResourceSet();
SetupContext setupContext = SetupContext.createUserOnly(resourceSet);
User user = setupContext.getUser();
boolean enabled = user.isPreferenceRecorderDefault();
doSetRecorderEnabled(enabled);
return enabled;
}
return Boolean.parseBoolean(value);
}
public void setRecorderEnabled(boolean enabled)
{
if (isRecorderEnabled() != enabled)
{
try
{
doSetRecorderEnabled(enabled);
}
finally
{
if (enabled)
{
if (recorder == null)
{
recorder = new PreferencesRecorder();
}
}
else
{
if (recorder != null)
{
recorder.done();
recorder = null;
}
}
}
}
}
private void doSetRecorderEnabled(boolean enabled)
{
SETUP_UI_PREFERENCES.setValue(SetupUIPlugin.PREF_ENABLE_PREFERENCE_RECORDER, Boolean.toString(enabled));
try
{
SETUP_UI_PREFERENCES.save();
}
catch (IOException ex)
{
SetupUIPlugin.INSTANCE.log(ex);
}
}
private void handleRecording(final Shell shell, final Map<URI, String> values)
{
final RecorderTransaction transaction = RecorderTransaction.open();
try
{
for (Iterator<URI> it = values.keySet().iterator(); it.hasNext();)
{
URI uri = it.next();
String path = PreferencesFactory.eINSTANCE.convertURI(uri);
Boolean policy = transaction.getPolicy(path);
if (policy == null)
{
transaction.setPolicy(path, true);
}
else if (!policy)
{
it.remove();
}
}
if (transaction.isDirty())
{
final boolean[] exitEarly = { false };
UIUtil.syncExec(display, new Runnable()
{
public void run()
{
RecorderPoliciesDialog reviewDialog = new RecorderPoliciesDialog(shell, transaction, values);
int result = reviewDialog.open();
if (!reviewDialog.isEnablePreferenceRecorder())
{
setRecorderEnabled(false);
exitEarly[0] = true;
}
else if (result != RecorderPoliciesDialog.OK)
{
exitEarly[0] = true;
}
}
});
if (exitEarly[0])
{
return;
}
}
transaction.setPreferences(values);
transaction.commit();
}
finally
{
transaction.close();
}
}
@SuppressWarnings("restriction")
private static boolean isPreferenceDialog(Shell shell)
{
Object data = shell.getData();
return data instanceof org.eclipse.ui.internal.dialogs.WorkbenchPreferenceDialog;
}
@SuppressWarnings("restriction")
private static void hookRecorderCheckbox(final Shell shell)
{
try
{
org.eclipse.ui.internal.dialogs.WorkbenchPreferenceDialog dialog = (org.eclipse.ui.internal.dialogs.WorkbenchPreferenceDialog)shell.getData();
if (dialog.buttonBar instanceof Composite)
{
Composite buttonBar = (Composite)dialog.buttonBar;
Control[] children = buttonBar.getChildren();
if (children.length != 0)
{
Control child = children[0];
if (child instanceof ToolBar)
{
ToolBar toolBar = (ToolBar)child;
toolItem = new ToolItem(toolBar, SWT.PUSH);
updateRecorderCheckboxState();
toolItem.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
boolean recorderEnabled = INSTANCE.isRecorderEnabled();
INSTANCE.setRecorderEnabled(!recorderEnabled);
updateRecorderCheckboxState();
RecorderPreferencePage.updateEnablement();
}
});
toolItem.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
toolItem = null;
}
});
buttonBar.layout();
}
}
}
}
catch (Throwable ex)
{
// Ignore.
}
}
static void updateRecorderCheckboxState()
{
if (toolItem != null)
{
boolean recorderEnabled = INSTANCE.isRecorderEnabled();
String state = recorderEnabled ? "enabled" : "disabled";
String verb = !recorderEnabled ? "enable" : "disable";
toolItem.setImage(SetupUIPlugin.INSTANCE.getSWTImage("recorder_" + state));
toolItem.setToolTipText("Oomph preference recorder " + state + " - Push to " + verb);
}
}
/**
* @author Eike Stepper
*/
public static class Lifecycle
{
public static void start(Display display)
{
INSTANCE.display = display;
display.addListener(SWT.Skin, INSTANCE.displayListener);
}
public static void stop()
{
INSTANCE.displayListener.stop();
if (INSTANCE.display != null)
{
UIUtil.asyncExec(INSTANCE.display, new Runnable()
{
public void run()
{
if (!INSTANCE.display.isDisposed())
{
INSTANCE.display.removeListener(SWT.Skin, INSTANCE.displayListener);
}
}
});
}
}
}
/**
* @author Eike Stepper
*/
private final class DisplayListener implements Listener
{
private boolean stopped;
public void stop()
{
stopped = true;
}
public void handleEvent(Event event)
{
if (stopped)
{
return;
}
if (event.widget instanceof Shell)
{
final Shell shell = (Shell)event.widget;
if (isPreferenceDialog(shell) && toolItem == null)
{
UIUtil.asyncExec(display, new Runnable()
{
public void run()
{
hookRecorderCheckbox(shell);
}
});
if (isRecorderEnabled())
{
recorder = new PreferencesRecorder();
}
shell.addDisposeListener(new DisposeListener()
{
public void widgetDisposed(DisposeEvent e)
{
if (recorder == null)
{
return;
}
final Map<URI, String> values = recorder.done();
recorder = null;
for (Iterator<URI> it = values.keySet().iterator(); it.hasNext();)
{
URI uri = it.next();
String pluginID = uri.segment(0);
if (SetupUIPlugin.PLUGIN_ID.equals(pluginID) && SetupUIPlugin.PREF_ENABLE_PREFERENCE_RECORDER.equals(uri.lastSegment()))
{
it.remove();
}
}
if (values.isEmpty())
{
RecorderTransaction transaction = RecorderTransaction.getInstance();
if (transaction != null)
{
// Close a transaction that has been opened by the RecorderPreferencePage.
transaction.close();
}
}
else
{
Job job = new Job("Store preferences")
{
@Override
protected IStatus run(IProgressMonitor monitor)
{
handleRecording(shell, values);
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
}
});
}
}
}
}
}