/***************************************************************************** * Copyright (c) 2010, 2015 CEA LIST, Christian W. Damus, 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: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Christian W. Damus - bug 482930 * Christian W. Damus - bug 482927 * Christian W. Damus - bug 469188 *****************************************************************************/ package org.eclipse.papyrus.views.properties.preferences; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExecutableExtension; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.papyrus.views.properties.contexts.Context; import org.eclipse.papyrus.views.properties.messages.Messages; import org.eclipse.papyrus.views.properties.runtime.ConfigurationConflict; import org.eclipse.papyrus.views.properties.runtime.ConfigurationManager; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; 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.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; /** * The PreferencePage for the Papyrus Property View. Offers an UI to enable or disable * property view contexts. * * @author Camille Letavernier */ public class Preferences extends PreferencePage implements IWorkbenchPreferencePage, IExecutableExtension { /** * The unique identifier of the default preference page, covering the Properties View. * * @see #getID() */ public static final String DEFAULT_ID = "org.eclipse.papyrus.views.properties.propertyview"; //$NON-NLS-1$ private String id; @Override public void init(IWorkbench workbench) { // Nothing } /** * Queries my unique identifier as configured on the extension point. * * @return my unique identifier */ public final String getID() { return id; } @Override public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { this.id = config.getAttribute("id"); //$NON-NLS-1$ } @Override protected Control createContents(Composite parent) { Composite self = new Composite(parent, SWT.NONE); self.setLayout(new GridLayout(1, false)); self.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); createHeaderContents(self); Label label = new Label(self, SWT.NONE); label.setText(Messages.Preferences_Contexts); final ConfigurationManager configurationManager = ConfigurationManager.getInstance(); List sortedContexts = configurationManager.getContextsForPreferencePage(getID()).stream() .sorted(contextOrdering()) .collect(Collectors.toList()); for (Context context : sortedContexts) { boolean applied = configurationManager.isApplied(context); Button checkbox = new Button(self, SWT.CHECK); checkbox.setText(getLabel(context)); checkbox.setSelection(applied); final Context theContext = context; contextState.setContextState(theContext, applied); checkbox.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { contextState.setContextState(theContext, ((Button) e.widget).getSelection()); } @Override public void widgetDefaultSelected(SelectionEvent e) { // Nothing } }); checkboxes.put(context, checkbox); } createFooterContents(self); contextState.snapshot(); return null; } /** * Overridden by subclasses to create optional header content above the * list of context check-boxes. * * @param parent * the parent composite */ protected void createHeaderContents(Composite parent) { // Pass } /** * Overridden by subclasses to create optional footer content below the * list of context check-boxes. * * @param parent * the parent composite */ protected void createFooterContents(Composite parent) { // Pass } protected Comparator contextOrdering() { return Comparator.comparingInt(this::getCategory).thenComparing( Comparator.comparing(Context::getUserLabel)); } protected int getCategory(Context context) { ConfigurationManager mgr = ConfigurationManager.getInstance(); return mgr.isCustomizable(context) ? mgr.isPlugin(context) ? 0 : 1 : 1000; } @Override public boolean performOk() { return contextState.saveContext() && super.performOk(); } @Override public void performApply() { contextState.saveContext(); } @Override public void performDefaults() { for (Context context : ConfigurationManager.getInstance().getContexts()) { boolean applied = ConfigurationManager.getInstance().isAppliedByDefault(context); Button checkbox = checkboxes.get(context); if (checkbox != null) { checkbox.setSelection(applied); contextState.setContextState(context, applied); } } } private String getLabel(Context context) { String qualifier; if (ConfigurationManager.getInstance().isPlugin(context)) { qualifier = Messages.Preferences_Plugin; } else if (ConfigurationManager.getInstance().isMissing(context)) { qualifier = "missing"; } else { qualifier = Messages.Preferences_Custom; } return String.format("%s (%s)", context.getUserLabel(), qualifier); //$NON-NLS-1$ } private final ContextState contextState = new ContextState(); private Map checkboxes = new HashMap(); private class ContextState { private Map contexts = new HashMap<>(); private Map snapshot; ContextState() { super(); } void snapshot() { snapshot = new HashMap<>(contexts); } public void setContextState(Context context, boolean applied) { contexts.put(context, applied); } public boolean saveContext() { for (Entry entry : contexts.entrySet()) { if (entry.getValue()) { ConfigurationManager.getInstance().enableContext(entry.getKey(), false); } else { ConfigurationManager.getInstance().disableContext(entry.getKey(), false); } } ConfigurationManager.getInstance().update(); Set delta = getChangedContexts(); if (!delta.isEmpty()) { Collection conflicts = ConfigurationManager.getInstance().checkConflicts(delta); if (!conflicts.isEmpty()) { String errorMessage = Messages.Preferences_ConflictWarning1; for (ConfigurationConflict conflict : conflicts) { errorMessage += conflict.toString() + "\n"; //$NON-NLS-1$ } errorMessage += Messages.Preferences_ConflictWarning2; MessageDialog dialog = new MessageDialog(getShell(), Messages.Preferences_ConflictWarningTitle, null, errorMessage, MessageDialog.WARNING, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 1); int result = dialog.open(); if (result != 0) { return false; } } snapshot(); } return true; } Set getChangedContexts() { return (snapshot == null) ? contexts.keySet() : snapshot.keySet().stream() .filter(c -> !Objects.equals(snapshot.get(c), contexts.get(c))) .collect(Collectors.toSet()); } } }