/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* 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
*******************************************************************************/
package gov.redhawk.ide.snapshot.ui;
import gov.redhawk.ide.snapshot.writer.IDataWriterDesc;
import gov.redhawk.ui.util.EmptyStringToNullConverter;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ViewerProperties;
import org.eclipse.jface.databinding.wizard.WizardPageSupport;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.actions.CreateFolderAction;
import org.eclipse.ui.actions.DeleteResourceAction;
import org.eclipse.ui.actions.NewProjectAction;
import org.eclipse.ui.actions.RefreshAction;
import org.eclipse.ui.actions.RenameResourceAction;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
public class SnapshotWizardPage extends WizardPage {
private static final int UPDATE_DELAY_MS = 100;
// === BEGIN: dialog page settings storage keys ===
private static final String SS_FILE_TYPE_ID = "outFileType_id";
private static final String SS_SAVE_TO_WORKSPACE = "saveToWorkspace";
private static final String SS_CONFIRM_OVERWRITE = "confirmOverwrite";
private static final String SS_FILESYSTEM_FILENAME = "filename";
private static final String SS_WORKSPACE_FILENAME = "workspaceFilename";
// === END: dialog page settings storage keys ===
private final SnapshotSettings settings = new SnapshotSettings();
private DataBindingContext context;
private WizardPageSupport support;
private IDialogSettings pageSettings;
private StackLayout fileFinderLayout;
private Composite searchWorkbench;
private Composite searchFileSystem;
private Group fileFinder;
private Button workspaceCheck;
public SnapshotWizardPage(String pageName, String title, ImageDescriptor titleImage) {
super(pageName, title, titleImage);
context = new DataBindingContext();
}
public DataBindingContext getContext() {
return context;
}
@Override
public void createControl(Composite main) {
setupDialogSettingsStorage(); // for saving wizard page settings
final Composite parent = new Composite(main, SWT.None);
parent.setLayout(GridLayoutFactory.fillDefaults().numColumns(3).create());
createOutputControls(parent);
setPageComplete(false);
setPageSupport(WizardPageSupport.create(this, context));
setControl(parent);
}
protected void setPageSupport(WizardPageSupport support) {
this.support = support;
}
public WizardPageSupport getPageSupport() {
return support;
}
protected void createOutputControls(final Composite parent) {
Label label;
// Add Label and combo box to select file type
label = new Label(parent, SWT.None);
label.setText("File Type:");
ComboViewer fileTypeCombo = new ComboViewer(parent, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.SIMPLE);
fileTypeCombo.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(2, 1).create());
fileTypeCombo.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
return ((IDataWriterDesc) element).getName();
}
});
fileTypeCombo.setContentProvider(ArrayContentProvider.getInstance()); // ArrayContentProvider does not store any state, therefore can re-use instances
IDataWriterDesc[] input = SnapshotActivator.getDataReceiverRegistry().getRecieverDescs();
fileTypeCombo.setInput(input);
fileTypeCombo.setComparator(new ViewerComparator()); // sort combo items alphabetically (this selects last item?)
@SuppressWarnings("unchecked")
IObservableValue< ? > dataWriterObservable = BeanProperties.value(settings.getClass(), "dataWriter").observe(settings);
context.bindValue(ViewerProperties.singleSelection().observe(fileTypeCombo), dataWriterObservable);
if (input.length > 0) {
fileTypeCombo.setSelection(new StructuredSelection(fileTypeCombo.getElementAt(0))); // select first sorted element
}
// add check box to see if the user wants to save to their workspace
workspaceCheck = new Button(parent, SWT.CHECK);
workspaceCheck.setText("Save to Workspace");
// add check box to see if user wants to confirm overwrite of existing file(s)
final Button confirmOverwrite = new Button(parent, SWT.CHECK);
confirmOverwrite.setText("Confirm overwrite");
@SuppressWarnings("unchecked")
IObservableValue< ? > confirmOverwriteObservable = BeanProperties.value(settings.getClass(), "confirmOverwrite").observe(settings);
context.bindValue(WidgetProperties.selection().observe(confirmOverwrite), confirmOverwriteObservable);
// region to hold the different pages for saving to the workspace or the file system
fileFinder = new Group(parent, SWT.SHADOW_ETCHED_IN);
fileFinder.setText("Save to");
fileFinder.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(3, 2).create());
fileFinderLayout = new StackLayout();
fileFinderLayout.marginHeight = 5;
fileFinderLayout.marginWidth = 5;
fileFinder.setLayout(fileFinderLayout);
// the different pages: search file system, search workspace
searchFileSystem = makeFileSystemSave(fileFinder);
searchFileSystem.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(3, 2).create());
searchWorkbench = makeWorkbenchTree(fileFinder);
searchWorkbench.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(3, 2).create());
// This binding must be defined after all controls have been configured, because its update strategy
// implementation calls setSaveLocation(), which depends on the controls being already configured
@SuppressWarnings("unchecked")
IObservableValue< ? > saveToWorkspaceObservable = BeanProperties.value(settings.getClass(), "saveToWorkspace").observe(settings);
context.bindValue(WidgetProperties.selection().observe(workspaceCheck), saveToWorkspaceObservable, createWsCheckUpdateStrategy(),
createWsCheckUpdateStrategy());
restoreWidgetValues(settings);
// determining which page starts on top
setSaveLocationComposite(workspaceCheck.getSelection(), true);
// switching pages
workspaceCheck.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
setSaveLocationComposite(workspaceCheck.getSelection(), true);
}
});
}
private void setSaveLocationComposite(final boolean workspace, final boolean updateModel) {
if (workspace) {
fileFinderLayout.topControl = searchWorkbench;
fileFinder.layout();
} else {
fileFinderLayout.topControl = searchFileSystem;
fileFinder.layout();
}
if (updateModel) {
context.updateModels(); // <-- this will update filename validators
}
}
private UpdateValueStrategy createFilenameT2MUpdateStrategy(final String fieldName, final boolean onWorkspace) {
UpdateValueStrategy updateValueStrategy = new UpdateValueStrategy();
updateValueStrategy.setConverter(new EmptyStringToNullConverter());
updateValueStrategy.setAfterConvertValidator(new IValidator() {
@Override
public IStatus validate(Object value) {
if (onWorkspace == settings.isSaveToWorkspace()) {
if (value instanceof String) {
return ValidationStatus.ok();
}
return ValidationStatus.error(fieldName + " must be specified.");
}
return ValidationStatus.ok();
}
});
return updateValueStrategy;
}
private UpdateValueStrategy createWsCheckUpdateStrategy() {
UpdateValueStrategy updateValueStrategy = new UpdateValueStrategy() {
@Override
public Object convert(Object value) {
if (value instanceof Boolean) {
setSaveLocationComposite((Boolean) value, false);
}
return super.convert(value);
}
};
return updateValueStrategy;
}
private UpdateValueStrategy createWorkspaceTreeT2MUpdateStrategy(final TreeViewer viewer) {
UpdateValueStrategy updateValueStrategy = new UpdateValueStrategy();
updateValueStrategy.setAfterConvertValidator(new IValidator() {
@Override
public IStatus validate(Object value) {
// Only do this validation if the workspaceCheck button returns true
if (workspaceCheck.getSelection()) {
if (((WorkbenchContentProvider) viewer.getContentProvider()).getElements(ResourcesPlugin.getWorkspace().getRoot()).length == 0) {
return ValidationStatus.error("A workspace project must be created.");
}
if (((IStructuredSelection) viewer.getSelection()).isEmpty()) {
return ValidationStatus.error("A workspace project must be selected.");
}
}
return ValidationStatus.ok();
}
});
return updateValueStrategy;
}
private Composite makeFileSystemSave(Composite parent) {
Composite comp = new Composite(parent, SWT.None);
comp.setLayout(GridLayoutFactory.fillDefaults().numColumns(3).create());
// the label and text field for files from the file system
Label fileNameLbl = new Label(comp, SWT.None);
fileNameLbl.setText("File Name:");
final Text fileNameTxt = new Text(comp, SWT.BORDER);
fileNameTxt.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(1, 1).create());
UpdateValueStrategy fnameTargetToModelValidator = createFilenameT2MUpdateStrategy("File Name", false);
@SuppressWarnings("unchecked")
IObservableValue< ? > filenameObservable = BeanProperties.value(settings.getClass(), "fileName").observe(settings);
context.bindValue(WidgetProperties.text(SWT.Modify).observeDelayed(UPDATE_DELAY_MS, fileNameTxt), filenameObservable,
fnameTargetToModelValidator, null);
// the browse button
Button button = new Button(comp, SWT.PUSH);
button.setText("Browse");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
String fileName = dialog.open();
if (fileName != null) {
fileNameTxt.setText(fileName);
}
}
});
return comp;
}
private Composite makeWorkbenchTree(Composite parent) {
Composite comp = new Composite(parent, SWT.None);
comp.setLayout(GridLayoutFactory.fillDefaults().numColumns(3).create());
// create label and text field for inputing the file name
Label fileNameLbl = new Label(comp, SWT.None);
fileNameLbl.setText("Workspace File Name:");
final Text fileNameTxt = new Text(comp, SWT.BORDER);
UpdateValueStrategy wkspFnameTargetToModelValidator = createFilenameT2MUpdateStrategy("Workspace File Name", true);
@SuppressWarnings("unchecked")
IObservableValue< ? > pathObservable = BeanProperties.value(settings.getClass(), "path").observe(settings);
context.bindValue(WidgetProperties.text(SWT.Modify).observeDelayed(UPDATE_DELAY_MS, fileNameTxt), pathObservable,
wkspFnameTargetToModelValidator, null);
fileNameTxt.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(2, 1).create());
// create tree with which to navigate the workbench file system
final TreeViewer workbenchTree = new TreeViewer(comp, SWT.BORDER | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION);
WorkbenchContentProvider contentProvider = new WorkbenchContentProvider();
workbenchTree.setContentProvider(contentProvider);
final WorkbenchLabelProvider labels = new WorkbenchLabelProvider();
workbenchTree.setLabelProvider(labels);
workbenchTree.setInput(ResourcesPlugin.getWorkspace().getRoot());
workbenchTree.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(3, 1).hint(SWT.DEFAULT, 150).create());
UpdateValueStrategy wkspTreeTargetToModelValidator = createWorkspaceTreeT2MUpdateStrategy(workbenchTree);
@SuppressWarnings("unchecked")
IObservableValue< ? >resourceObservable = BeanProperties.value(settings.getClass(), "resource").observe(settings);
context.bindValue(ViewerProperties.singleSelection().observe(workbenchTree), resourceObservable,
wkspTreeTargetToModelValidator, null);
Object[] elements = contentProvider.getElements(ResourcesPlugin.getWorkspace().getRoot());
if (elements.length > 0) {
workbenchTree.setSelection(new StructuredSelection(elements[0]));
}
workbenchTree.addFilter(new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof IResource) {
IResource resource = (IResource) element;
if (resource.getName().isEmpty() || resource.getName().charAt(0) == '.') {
return false;
}
}
return true;
}
});
IShellProvider shellProvider = new IShellProvider() {
@Override
public Shell getShell() {
return SnapshotWizardPage.this.getShell();
}
};
final CreateFolderAction folderAction = new CreateFolderAction(shellProvider);
final DeleteResourceAction deleteAction = new DeleteResourceAction(shellProvider);
final RefreshAction refreshAction = new RefreshAction(shellProvider);
final RenameResourceAction renamAction = new RenameResourceAction(shellProvider);
final NewProjectAction projectAction = new NewProjectAction();
workbenchTree.addSelectionChangedListener(folderAction);
workbenchTree.addSelectionChangedListener(deleteAction);
workbenchTree.addSelectionChangedListener(refreshAction);
workbenchTree.addSelectionChangedListener(renamAction);
// the menu for the tree items
MenuManager contextMenuManager = new MenuManager();
contextMenuManager.setRemoveAllWhenShown(true);
contextMenuManager.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager manager) {
manager.add(projectAction);
manager.add(folderAction);
manager.add(renamAction);
manager.add(refreshAction);
manager.add(deleteAction);
}
});
Menu menu = contextMenuManager.createContextMenu(workbenchTree.getControl());
workbenchTree.getControl().setMenu(menu);
return comp;
}
@Override
public void dispose() {
if (support != null) {
support.dispose();
support = null;
}
if (context != null) {
context.dispose();
context = null;
}
super.dispose();
}
public SnapshotSettings getSettings() {
return settings;
}
public void setupDialogSettingsStorage() {
pageSettings = getDialogSettings().getSection(getName());
if (pageSettings == null) {
pageSettings = getDialogSettings().addNewSection(getName());
}
}
protected IDialogSettings getPageSettingsSection() {
return pageSettings;
}
protected void saveWidgetValues(SnapshotSettings ss) {
pageSettings.put(SS_FILE_TYPE_ID, ss.getDataWriter().getID());
pageSettings.put(SS_SAVE_TO_WORKSPACE, ss.isSaveToWorkspace());
pageSettings.put(SS_CONFIRM_OVERWRITE, ss.isConfirmOverwrite());
pageSettings.put(SS_FILESYSTEM_FILENAME, ss.getFileName());
pageSettings.put(SS_WORKSPACE_FILENAME, ss.getPath());
}
private void restoreWidgetValues(SnapshotSettings sss) {
String tmp;
tmp = pageSettings.get(SS_FILE_TYPE_ID);
if (tmp != null) {
IDataWriterDesc dwd = SnapshotActivator.getDataReceiverRegistry().getRecieverDesc(tmp);
if (dwd != null) {
sss.setDataWriter(dwd);
}
}
tmp = pageSettings.get(SS_SAVE_TO_WORKSPACE);
if (tmp != null) {
sss.setSaveToWorkspace(Boolean.valueOf(tmp));
}
tmp = pageSettings.get(SS_CONFIRM_OVERWRITE);
if (tmp != null) {
sss.setConfirmOverwrite(Boolean.valueOf(tmp));
}
sss.setFileName(pageSettings.get(SS_FILESYSTEM_FILENAME));
sss.setPath(pageSettings.get(SS_WORKSPACE_FILENAME));
}
}