blob: 0b809bd1abfd6d52c94d1807eb25079965c4ef62 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2012 SpringSource, a divison of VMware, Inc.
* 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:
* SpringSource, a division of VMware, Inc. - initial API and implementation
* GianMaria Romanato - multiple selection and apply changes on save
*******************************************************************************/
package org.eclipse.virgo.ide.runtime.internal.ui.editor;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.AbstractOperation;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Table;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.virgo.ide.runtime.core.IServerWorkingCopy;
import org.eclipse.virgo.ide.runtime.internal.core.actions.ModifyArtefactOrderCommand;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.ui.ServerUICore;
import org.eclipse.wst.server.ui.editor.ServerEditorSection;
/**
* {@link ServerEditorSection} section that allows to configure the JMX deployer credentials.
*
* Largely rewritten to allow multiple selection and to avoid that user actions are immediately applied to the server
* configuration. Changes are now applied only when the user saves the editor.
*
* @author Christian Dupuis
* @author Steffen Pingel
* @author GianMaria Romanato - support multiple selection and apply changes to configuration only when editor is saved
* @since 1.0.1
*/
public class ArtefactOrderEditorSection extends ServerEditorSection {
/**
* An operation used for making ordering changes in the UI, triggering dirty state and supporting UNDO.
*
* Changes are applied to the server only when the editor is saved using a different operation, see
* {@link ArtefactOrderEditorSection#doSave(IProgressMonitor)}
*/
private class ModifyArtefactOrderEditorCommand extends AbstractOperation {
private List<IModule> oldOrder;
private final List<IModule> newOrder;
ModifyArtefactOrderEditorCommand(List<IModule> newOrder) {
super("Modify artefact order in editor UI"); //$NON-NLS-1$
this.newOrder = newOrder;
}
@Override
public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
this.oldOrder = ArtefactOrderEditorSection.this.orderedModules;
ArtefactOrderEditorSection.this.orderedModules = this.newOrder;
ArtefactOrderEditorSection.this.bundleTableViewer.setInput(ArtefactOrderEditorSection.this.orderedModules);
return Status.OK_STATUS;
}
@Override
public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
return execute(monitor, info);
}
@Override
public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
ArtefactOrderEditorSection.this.orderedModules = this.oldOrder;
this.oldOrder = null;
ArtefactOrderEditorSection.this.bundleTableViewer.setInput(ArtefactOrderEditorSection.this.orderedModules);
return Status.OK_STATUS;
}
}
protected IServerWorkingCopy serverWorkingCopy;
// represents the model for the table
private List<IModule> orderedModules;
protected boolean updating;
protected PropertyChangeListener listener;
private Table bundleTable;
private TableViewer bundleTableViewer;
private Button upButton;
private Button downButton;
protected void addConfigurationChangeListener() {
this.listener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if (ArtefactOrderEditorSection.this.updating) {
return;
}
ArtefactOrderEditorSection.this.updating = true;
if (org.eclipse.virgo.ide.runtime.core.IServer.PROPERTY_ARTEFACT_ORDER
.equals(event.getPropertyName())) {
initialize();
}
ArtefactOrderEditorSection.this.updating = false;
}
};
this.serverWorkingCopy.addConfigurationChangeListener(this.listener);
}
@Override
public void createSection(Composite parent) {
super.createSection(parent);
FormToolkit toolkit = getFormToolkit(parent.getDisplay());
Section section = toolkit.createSection(parent, ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED
| ExpandableComposite.TITLE_BAR | Section.DESCRIPTION | ExpandableComposite.FOCUS_TITLE);
section.setText(Messages.ArtefactOrderEditorSection_title);
section.setDescription(Messages.ArtefactOrderEditorSection_description);
section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
Composite composite = toolkit.createComposite(section);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginHeight = 5;
layout.marginWidth = 1;
layout.verticalSpacing = 5;
layout.horizontalSpacing = 1;
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL, GridData.FILL_VERTICAL, true, true));
toolkit.paintBordersFor(composite);
section.setClient(composite);
this.bundleTable = toolkit.createTable(composite, SWT.MULTI | SWT.V_SCROLL | SWT.FULL_SELECTION);
GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
int modulesNumber = this.server.getModules().length;
data.heightHint = this.bundleTable.getItemHeight() * Math.min(Math.max(5, modulesNumber), 10)
+ this.bundleTable.getBorderWidth() * 2;
this.bundleTable.setLayoutData(data);
this.bundleTableViewer = new TableViewer(this.bundleTable);
this.bundleTableViewer.setContentProvider(new ArrayContentProvider());
this.bundleTableViewer.setLabelProvider(ServerUICore.getLabelProvider());
this.bundleTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
updateButtons(event.getSelection());
}
});
Composite buttonComposite = new Composite(composite, SWT.NONE);
buttonComposite.setLayout(new GridLayout(1, true));
data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
buttonComposite.setLayoutData(data);
this.upButton = toolkit.createButton(buttonComposite, Messages.ArtefactOrderEditorSection_up_button, SWT.PUSH);
data = new GridData();
this.upButton.setLayoutData(data);
this.upButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
IStructuredSelection selection = (IStructuredSelection) ArtefactOrderEditorSection.this.bundleTableViewer
.getSelection();
List<IModule> allModules = new ArrayList<IModule>(ArtefactOrderEditorSection.this.orderedModules);
for (IModule aModule : (List<IModule>) selection.toList()) {
int index = allModules.indexOf(aModule);
allModules.remove(aModule);
allModules.add(index - 1, aModule);
}
execute(new ModifyArtefactOrderEditorCommand(allModules));
updateButtons(selection);
}
});
this.downButton = toolkit.createButton(buttonComposite, Messages.ArtefactOrderEditorSection_down_button,
SWT.PUSH);
this.downButton.setLayoutData(data);
this.downButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
IStructuredSelection selection = (IStructuredSelection) ArtefactOrderEditorSection.this.bundleTableViewer
.getSelection();
List<IModule> allModules = new ArrayList<IModule>(ArtefactOrderEditorSection.this.orderedModules);
List<IModule> reversedSelection = new ArrayList<IModule>(selection.toList());
Collections.reverse(reversedSelection);
for (IModule aModule : reversedSelection) {
int index = allModules.indexOf(aModule);
allModules.remove(aModule);
allModules.add(index + 1, aModule);
}
execute(new ModifyArtefactOrderEditorCommand(allModules));
updateButtons(selection);
}
});
initialize();
}
/**
* @see ServerEditorSection#dispose()
*/
@Override
public void dispose() {
if (this.server != null) {
this.server.removePropertyChangeListener(this.listener);
}
}
/**
* @see ServerEditorSection#init(IEditorSite, IEditorInput)
*/
@Override
public void init(IEditorSite site, IEditorInput input) {
super.init(site, input);
this.serverWorkingCopy = (IServerWorkingCopy) this.server.loadAdapter(IServerWorkingCopy.class,
new NullProgressMonitor());
addConfigurationChangeListener();
}
/**
* Initialize model and view.
*/
protected void initialize() {
final List<String> orderedArtefacts = this.serverWorkingCopy.getConfiguration().getArtefactOrder();
this.orderedModules = new ArrayList(Arrays.asList(this.server.getModules()));
// sort the modules according the order defined in the server configuration
Collections.sort(this.orderedModules, new java.util.Comparator<IModule>() {
public int compare(IModule o1, IModule o2) {
Integer m1 = orderedArtefacts.contains(o1.getId())
? orderedArtefacts.indexOf(o1.getId())
: Integer.MAX_VALUE;
Integer m2 = orderedArtefacts.contains(o2.getId())
? orderedArtefacts.indexOf(o2.getId())
: Integer.MAX_VALUE;
return m1.compareTo(m2);
}
});
this.bundleTableViewer.setInput(this.orderedModules);
}
private void updateButtons(ISelection selections) {
IStructuredSelection ss = (IStructuredSelection) selections;
List<IModule> selectedModules = ss.toList();
List<IModule> allModules = this.orderedModules;
final int lowerBound = allModules.size() - 1;
boolean initialState = !selections.isEmpty() && !allModules.isEmpty();
boolean canMoveUp = initialState;
boolean canMoveDown = initialState;
for (int i = 0; i < selectedModules.size() && initialState; i++) {
IModule obj = selectedModules.get(i);
int index = allModules.indexOf(obj);
canMoveUp = canMoveUp && index > 0;
canMoveDown = canMoveDown && index < lowerBound;
}
this.upButton.setEnabled(canMoveUp);
this.downButton.setEnabled(canMoveDown);
}
@Override
public void doSave(IProgressMonitor monitor) {
List<String> artefactOrder = new ArrayList<String>();
for (Object module : this.orderedModules) {
artefactOrder.add(((IModule) module).getId());
}
if (!this.serverWorkingCopy.getArtefactOrder().equals(artefactOrder)) {
this.updating = true;
execute(new ModifyArtefactOrderCommand(this.serverWorkingCopy, artefactOrder));
this.updating = false;
}
}
}