blob: 399c8dc81eb1152b0cea33adc265a573bb34d91b [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation 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:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.ui.forms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.epf.authoring.ui.AuthoringUIPlugin;
import org.eclipse.epf.authoring.ui.AuthoringUIResources;
import org.eclipse.epf.authoring.ui.AuthoringUIText;
import org.eclipse.epf.authoring.ui.editors.EditorChooser;
import org.eclipse.epf.authoring.ui.editors.MethodElementEditor;
import org.eclipse.epf.authoring.ui.views.ViewHelper;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.command.RemoveReferencesCommand;
import org.eclipse.epf.library.edit.util.Comparators;
import org.eclipse.epf.library.edit.util.Misc;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.ui.LibraryUIText;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.PluginReferenceChecker;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.ModifyListener;
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.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
/**
* Description page for method plugin
*
* @author Shilpa Toraskar
* @author Kelvin Low
* @author Phong Nguyen Le
* @since 1.0
* fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=176382
*/
public class MethodPluginDescriptionPage extends DescriptionFormPage implements IRefreshable {
protected static final String FORM_PREFIX = LibraryUIText.TEXT_METHOD_PLUGIN
+ ": "; //$NON-NLS-1$
protected Text ctrl_r_brief_desc;
protected CheckboxTableViewer ctrl_refModel;
protected Section refModelSection;
protected Composite refModelComposite;
protected MethodPlugin plugin;
protected Button ctrl_changeable;
protected Button supportingPluginCheckbox;
public boolean notificationEnabled = true;
protected Adapter userChangeableAdapter;
// protected ModifyListener nameModifyListener;
protected ISelectionChangedListener refModelSelChangedListener = new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
StructuredSelection selectedList = (StructuredSelection) event
.getSelection();
MethodPlugin selectedObj = (MethodPlugin) selectedList
.getFirstElement();
if (selectedObj == null)
return;
ctrl_r_brief_desc.setText(selectedObj
.getBriefDescription());
}
};
protected ICheckStateListener refModelCheckStateListener = new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
Object obj = event.getElement();
ctrl_r_brief_desc.setText(((MethodPlugin) obj)
.getBriefDescription());
if (TngUtil.isLocked(plugin)) {
ctrl_refModel.setChecked(obj, !event.getChecked());
return;
}
if (event.getChecked()) {
// TODO: Change this to be not un-doable due to the circular
// dependency check.
actionMgr.doAction(IActionManager.ADD, plugin,
UmaPackage.eINSTANCE.getMethodPlugin_Bases(),
(MethodPlugin) obj, -1);
} else {
final MethodPlugin base = (MethodPlugin) obj;
if(removeAllReferences(base)){
ctrl_refModel.setChecked(base, false);
}else{
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
ctrl_refModel.setChecked(base, true);
}
});
return;
}
// change this to be not un-doable due to the circular
// dependency check
// plugin.getBases().remove(obj);
actionMgr.doAction(IActionManager.REMOVE, plugin,
UmaPackage.eINSTANCE.getMethodPlugin_Bases(),
(MethodPlugin) obj, -1);
}
// double check circular dependency, not necessary here
PluginReferenceChecker.hasCircularConflictWithPlugin(plugin);
updateChangeDate();
}
};
/**
* Creates a new instance.
*/
public MethodPluginDescriptionPage(FormEditor editor) {
super(editor, AuthoringUIText.DESCRIPTION_PAGE_TITLE,
AuthoringUIText.DESCRIPTION_PAGE_TITLE);
userChangeableAdapter = new UserChangeableAdapter();
}
/**
* @see org.eclipse.epf.authoring.ui.forms.BaseFormPage#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
*/
public void init(IEditorSite site, IEditorInput input) {
super.init(site, input);
plugin = (MethodPlugin) methodElement;
if (userChangeableAdapter != null) {
plugin.eAdapters().add(userChangeableAdapter);
}
detailSectionOn = false;
fullDescOn = false;
keyConsiderationOn = false;
variabilitySectionOn = false;
}
/**
* @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#createEditorContent(FormToolkit)
*/
protected void createEditorContent(FormToolkit toolkit) {
super.createEditorContent(toolkit);
createReferenceSection(toolkit);
// Set focus on the Name text control.
Display display = form.getBody().getDisplay();
if (!(display == null || display.isDisposed())) {
display.asyncExec(new Runnable() {
public void run() {
if(ctrl_name.isDisposed()) return;
ctrl_name.setFocus();
ctrl_name.setSelection(0, ctrl_name.getText().length());
}
});
}
}
protected void createReferenceContent(FormToolkit toolkit) {
Table ctrl_table = toolkit.createTable(refModelComposite, SWT.CHECK);
{
GridData gridData = new GridData(GridData.BEGINNING
| GridData.FILL_BOTH);
gridData.heightHint = 100;
ctrl_table.setLayoutData(gridData);
}
ctrl_refModel = new CheckboxTableViewer(ctrl_table);
ILabelProvider labelProvider = new LabelProvider() {
public String getText(Object element) {
MethodPlugin plugin = (MethodPlugin) element;
return plugin.getName();
}
};
ctrl_refModel.setLabelProvider(labelProvider);
createRefModelBriefDescField(toolkit);
toolkit.paintBordersFor(refModelComposite);
}
protected void createRefModelBriefDescField(FormToolkit toolkit) {
Label l_r_brief_desc = toolkit.createLabel(refModelComposite,
AuthoringUIText.BRIEF_DESCRIPTION_TEXT);
{
GridData gridData = new GridData(GridData.BEGINNING);
gridData.horizontalSpan = 2;
l_r_brief_desc.setLayoutData(gridData);
}
ctrl_r_brief_desc = toolkit.createText(refModelComposite,
"", SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY); //$NON-NLS-1$
{
GridData gridData = new GridData(GridData.FILL_HORIZONTAL
| GridData.GRAB_HORIZONTAL);
gridData.heightHint = 80;
gridData.horizontalSpan = 2;
ctrl_r_brief_desc.setLayoutData(gridData);
}
}
protected void createReferenceSection(FormToolkit toolkit) {
// Ref Model Section
refModelSection = toolkit.createSection(sectionComposite,
Section.DESCRIPTION | Section.TWISTIE | Section.EXPANDED
| Section.TITLE_BAR);
GridData td1 = new GridData(GridData.FILL_BOTH);
refModelSection.setLayoutData(td1);
refModelSection
.setText(AuthoringUIText.REFERENCED_PLUGINS_SECTION_NAME);
refModelSection
.setDescription(AuthoringUIText.REFERENCED_PLUGINS_SECTION_DESC);
refModelSection.setLayout(new GridLayout());
refModelComposite = toolkit.createComposite(refModelSection);
refModelComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
refModelComposite.setLayout(new GridLayout(2, false));
refModelSection.setClient(refModelComposite);
createReferenceContent(toolkit);
}
protected void setCheckboxForCurrentBase(List<MethodPlugin> currentBaseList) {
ctrl_refModel.setAllChecked(false);
for (int i = 0; i < currentBaseList.size(); i++) {
MethodPlugin model = (MethodPlugin) currentBaseList.get(i);
ctrl_refModel.setChecked(model, true);
}
}
/**
* Add listeners
*
*/
protected void addListeners() {
super.addListeners();
final MethodElementEditor editor = (MethodElementEditor) getEditor();
form.addListener(SWT.Activate, new Listener() {
public void handleEvent(Event e) {
refreshReferencedModels();
if (!plugin.getUserChangeable().booleanValue()) {
refresh(false);
} else {
refresh(true);
}
}
});
ctrl_name.removeFocusListener(nameFocusListener);
// nameModifyListener = editor.createModifyListener(plugin, true);
// ctrl_name.addModifyListener(nameModifyListener);
ctrl_name.addListener(SWT.Deactivate, new Listener() {
public void handleEvent(Event e) {
String oldContent = plugin.getName();
if (((MethodElementEditor) getEditor()).mustRestoreValue(
e.widget, oldContent)) {
return;
}
if (ctrl_name.getText().equals(plugin.getName())) {
return;
}
// Check invalid characters first.
// 178462
String msg = null;
String name = ctrl_name.getText().trim();
if (name != null) {
if (oldContent.indexOf("&") < 0 && name.indexOf("&") > -1) { //$NON-NLS-1$ //$NON-NLS-2$
msg = NLS
.bind(
LibraryEditResources.invalidElementNameError4_msg,
name);
} else {
msg = LibraryUtil.checkPluginName(null, name);
}
}
String validName = StrUtil.makeValidFileName(ctrl_name
.getText());
if (msg == null) {
// Check duplicate plug-in name.
msg = LibraryUtil.checkPluginName(plugin, validName);
}
if (msg == null) {
if (!validName.equals(plugin.getName())) {
Shell shell = getSite().getShell();
msg = AuthoringUIResources.bind(AuthoringUIResources.methodPluginDescriptionPage_confirmRename, (new Object[] { plugin.getName(), ctrl_name.getText() }));
String title = AuthoringUIResources.methodPluginDescriptionPage_confirmRename_title;
if (!MessageDialog.openConfirm(shell, title, msg)) {
ctrl_name.setText(plugin.getName());
return;
}
e.doit = true;
EditorChooser.getInstance().closeMethodEditorsForPluginElements(plugin);
ctrl_name.setText(validName);
boolean status = actionMgr.doAction(IActionManager.SET,
plugin, UmaPackage.eINSTANCE
.getNamedElement_Name(), validName, -1);
if (!status) {
return;
}
form.setText(FORM_PREFIX + plugin.getName());
updateChangeDate();
// adjust plugin location and save the editor
//
BusyIndicator.showWhile(getSite().getShell()
.getDisplay(), new Runnable() {
public void run() {
MethodElementEditor editor = (MethodElementEditor) getEditor();
editor.doSave(new NullProgressMonitor());
ILibraryPersister.FailSafeMethodLibraryPersister persister = editor
.getPersister();
try {
persister
.adjustLocation(plugin.eResource());
persister.commit();
} catch (RuntimeException e) {
AuthoringUIPlugin.getDefault().getLogger()
.logError(e);
try {
persister.rollback();
} catch (Exception ex) {
AuthoringUIPlugin.getDefault()
.getLogger().logError(ex);
ViewHelper
.reloadCurrentLibaryOnRollbackError(getSite()
.getShell());
return;
}
AuthoringUIPlugin
.getDefault()
.getMsgDialog()
.displayWarning(
getSite().getShell()
.getText(),
AuthoringUIResources.methodPluginDescriptionPage_cannotRenamePluginFolder
, e.getMessage(), e);
}
}
});
}
} else {
ctrl_name.setText(plugin.getName());
Shell shell = getSite().getShell();
AuthoringUIPlugin.getDefault().getMsgDialog().displayError(
shell.getText(), msg);
e.doit = false;
ctrl_name.getDisplay().asyncExec(new Runnable() {
public void run() {
ctrl_name.setFocus();
ctrl_name.selectAll();
}
});
}
}
});
ctrl_name.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
((MethodElementEditor) getEditor()).setCurrentFeatureEditor(e.widget,
UmaPackage.eINSTANCE.getNamedElement_Name());
}
});
addReferencedModelListener();
}
protected void addReferencedModelListener() {
ctrl_refModel.addSelectionChangedListener(refModelSelChangedListener);
ctrl_refModel.addCheckStateListener(refModelCheckStateListener);
}
@Override
protected void refresh(boolean editable) {
super.refresh(editable);
ctrl_r_brief_desc.setEditable(false);
if(supportingPluginCheckbox != null) {
supportingPluginCheckbox.setEnabled(editable);
}
}
@Override
protected void createGeneralSectionContent() {
super.createGeneralSectionContent();
supportingPluginCheckbox = toolkit
.createButton(
generalComposite,
AuthoringUIResources.methodPluginDescriptionPage_supportingPluginLabel, SWT.CHECK);
}
@Override
protected void addGeneralSectionListeners() {
super.addGeneralSectionListeners();
supportingPluginCheckbox.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
IStatus status = TngUtil.checkEdit(plugin, getSite().getShell());
if (status.isOK()) {
boolean ret = actionMgr.doAction(IActionManager.SET,
plugin, UmaPackage.eINSTANCE
.getMethodPlugin_Supporting(),
new Boolean(supportingPluginCheckbox.getSelection()),
-1);
// in case of readonly file, roll back changes.
if (!ret) {
supportingPluginCheckbox.setSelection(!supportingPluginCheckbox
.getSelection());
return;
}
} else {
AuthoringUIPlugin.getDefault().getMsgDialog().displayError(
AuthoringUIResources.editDialog_title,
AuthoringUIResources.editDialog_msgCannotEdit,
status);
// restore old value
//
supportingPluginCheckbox.setSelection(!supportingPluginCheckbox.getSelection());
return;
}
}
});
}
@Override
protected void loadGeneralSectionData() {
super.loadGeneralSectionData();
supportingPluginCheckbox
.setSelection(plugin.isSupporting());
}
/**
* Create the Version section content.
*/
protected void createVersionSectionContent() {
super.createVersionSectionContent();
ctrl_changeable = toolkit
.createButton(
versionComposite,
AuthoringUIResources.methodPluginDescriptionPage_lockPluginLabel, SWT.CHECK);
}
protected void addVersionSectionListeners() {
super.addVersionSectionListeners();
ctrl_changeable.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
notificationEnabled = true;
IStatus status = TngUtil.checkEdit(plugin, getSite().getShell());
if (status.isOK()) {
String message = AuthoringUIResources
.bind(
AuthoringUIResources.methodPluginDescriptionPage_lockPlugin_message,
plugin.getName());
Shell shell = getSite().getShell();
if (AuthoringUIPlugin.getDefault().getMsgDialog()
.displayConfirmation(shell.getText(), message)) {
// close editors on any change in ctrl_changeable
// if (ctrl_changeable.getSelection()) {
EditorChooser.getInstance().closeMethodEditorsForPluginElements(plugin);
boolean ret = actionMgr.doAction(IActionManager.SET,
plugin, UmaPackage.eINSTANCE
.getMethodPlugin_UserChangeable(),
new Boolean(!ctrl_changeable.getSelection()),
-1);
// in case of readonly file, roll back changes.
if (!ret) {
ctrl_changeable.setSelection(!ctrl_changeable
.getSelection());
return;
}
// }
refresh(!ctrl_changeable.getSelection());
} else {
// actionMgr.undo();
ctrl_changeable.setSelection(!ctrl_changeable
.getSelection());
refresh(!ctrl_changeable.getSelection());
// return;
}
} else {
AuthoringUIPlugin.getDefault().getMsgDialog().displayError(
AuthoringUIResources.editDialog_title,
AuthoringUIResources.editDialog_msgCannotEdit,
status);
// restore old value
//
ctrl_changeable.setSelection(!ctrl_changeable.getSelection());
return;
}
copyright_viewer.refresh();
// refresh editor title image.
((MethodElementEditor)getEditor()).refreshTitleImage();
}
});
}
protected void loadVersionSectionData() {
super.loadVersionSectionData();
ctrl_changeable
.setSelection(!plugin.getUserChangeable().booleanValue());
}
protected class UserChangeableAdapter extends AdapterImpl {
public void notifyChanged(Notification msg) {
switch (msg.getFeatureID(MethodPlugin.class)) {
case UmaPackage.METHOD_PLUGIN__USER_CHANGEABLE:
Boolean b = (Boolean) msg.getNewValue();
setUserChangeable(b.booleanValue());
return;
}
}
}
public void setUserChangeable(boolean userChangeable) {
if (!notificationEnabled)
return;
notificationEnabled = false;
plugin.setUserChangeable(Boolean.valueOf(userChangeable));
}
/**
* @see org.eclipse.ui.forms.editor.FormPage#dispose()
*/
public void dispose() {
plugin.eAdapters().remove(userChangeableAdapter);
super.dispose();
}
/**
* Checks if the given MethodPlugin <code>base</code> is one in the given
* plugins collection or base of any plugin in the collection.
*
* @param base
* @param plugins
* @return
*/
protected static boolean isOneOrBaseOf(MethodPlugin base, Collection<MethodPlugin> plugins) {
for (MethodPlugin plugin : plugins) {
if(base == plugin || Misc.isBaseOf(base, plugin)) {
return true;
}
}
return false;
}
protected boolean removeAllReferences(MethodPlugin unCheckedPlugin) {
ArrayList<MethodPlugin> removedBases = new ArrayList<MethodPlugin>();
removedBases.add(unCheckedPlugin);
for (Iterator<MethodPlugin> iter = new AbstractTreeIterator<MethodPlugin>(unCheckedPlugin, false) {
private static final long serialVersionUID = 1L;
@Override
protected Iterator<? extends MethodPlugin> getChildren(Object object) {
if(object instanceof MethodPlugin && object != plugin) {
return ((MethodPlugin)object).getBases().iterator();
}
Collection<? extends MethodPlugin> empty = Collections.emptyList();
return empty.iterator();
}
}; iter.hasNext();) {
MethodPlugin base = iter.next();
ArrayList<MethodPlugin> plugins = new ArrayList<MethodPlugin>(plugin.getBases());
plugins.remove(unCheckedPlugin);
if(!isOneOrBaseOf(base, plugins)) {
removedBases.add(base);
}
}
ArrayList<MethodPlugin> affectedPlugins = new ArrayList<MethodPlugin>();
// get all plug-ins in library that extend this plug-in
//
List<?> plugins = LibraryService.getInstance().getCurrentMethodLibrary()
.getMethodPlugins();
for (Iterator<?> iterator = plugins.iterator(); iterator.hasNext();) {
MethodPlugin mp = (MethodPlugin) iterator.next();
if(mp != plugin && Misc.isBaseOf(plugin, mp)) {
affectedPlugins.add(mp);
}
}
ArrayList<RemoveReferencesCommand> commands = new ArrayList<RemoveReferencesCommand>();
for (MethodPlugin base : removedBases) {
if(UmaUtil.hasReference(plugin, base)) {
commands.add(new RemoveReferencesCommand(plugin, base));
}
for (MethodPlugin mp : affectedPlugins) {
ArrayList<MethodPlugin> bases = new ArrayList<MethodPlugin>(mp.getBases());
bases.remove(base);
if(!isOneOrBaseOf(base, bases) && UmaUtil.hasReference(mp, base)) {
commands.add(new RemoveReferencesCommand(mp, base));
}
}
}
if (!commands.isEmpty()) {
String message = AuthoringUIResources
.bind(AuthoringUIResources.methodPluginDescriptionRemoveRefConfirm_message,
plugin.getName());
Shell shell = getSite().getShell();
if (AuthoringUIPlugin.getDefault().getMsgDialog()
.displayConfirmation(shell.getText(), message)) {
int i = 0;
try {
for (RemoveReferencesCommand cmd : commands) {
actionMgr.execute(cmd);
i++;
}
return true;
}
catch(Exception e) {
AuthoringUIPlugin.getDefault().getLogger().logError(e);
// undo the executed commands
for (; i > 0; i--) {
actionMgr.undo();
}
return false;
}
} else {
return false;
}
}
return true;
}
/**
* @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#loadSectionDescription()
*/
public void loadSectionDescription() {
this.generalSectionDescription = AuthoringUIResources.plugin_generalInfoSection_desc;
this.versionSectionDescription = AuthoringUIResources.plugin_versionInfoSection_desc;
}
@Override
protected Object getContentElement() {
return plugin;
}
protected void refreshReferencedModels() {
// Clear the old items and add the newly allowable items.
ctrl_refModel.getTable().clearAll();
ctrl_refModel.refresh();
List allowableList = PluginReferenceChecker
.getApplicableBasePlugins(plugin);
Collections.<Object>sort(allowableList, Comparators.PLUGINPACKAGE_COMPARATOR);
ctrl_refModel.add(allowableList.toArray());
List<MethodPlugin> currentBaseList = plugin.getBases();
setCheckboxForCurrentBase(currentBaseList);
}
}