/******************************************************************************* * Copyright (c) 2008, 2017 xored software, Inc. 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: * xored software, Inc. - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.tcl.internal.ui.preferences; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; 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.dltk.core.DLTKCore; import org.eclipse.dltk.core.DLTKLanguageManager; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.dltk.internal.core.ProjectRefreshOperation; import org.eclipse.dltk.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.dltk.internal.ui.wizards.dialogfields.IDialogFieldListener; import org.eclipse.dltk.internal.ui.wizards.dialogfields.IListAdapter; import org.eclipse.dltk.internal.ui.wizards.dialogfields.ListDialogField; import org.eclipse.dltk.tcl.core.TclCorePreferences; import org.eclipse.dltk.tcl.core.TclNature; import org.eclipse.dltk.tcl.core.TclPlugin; import org.eclipse.dltk.tcl.internal.structure.TclSourceElementParser2; import org.eclipse.dltk.ui.preferences.AbstractConfigurationBlockPropertyAndPreferencePage; import org.eclipse.dltk.ui.preferences.AbstractOptionsBlock; import org.eclipse.dltk.ui.preferences.PreferenceKey; import org.eclipse.dltk.ui.util.IStatusChangeListener; import org.eclipse.dltk.ui.util.PixelConverter; import org.eclipse.dltk.ui.util.SWTFactory; import org.eclipse.dltk.utils.TextUtils; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.IFontProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.window.Window; import org.eclipse.swt.graphics.Font; 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.ui.preferences.IWorkbenchPreferenceContainer; @SuppressWarnings("restriction") public class TclCorePreferencePage extends AbstractConfigurationBlockPropertyAndPreferencePage { private static int IDX_ADD = 0; private static int IDX_EDIT = 1; private static int IDX_REMOVE = 2; protected static class TclCorePreferenceBlock extends AbstractOptionsBlock { private class TclCheckContentAdapter implements IListAdapter, IDialogFieldListener { private Set<String> contributedElements = null; private final PreferenceKey listKey; private final char itemSeparator; public TclCheckContentAdapter(PreferenceKey listKey, char listSeparator) { this.listKey = listKey; this.itemSeparator = listSeparator; } @Override public void customButtonPressed(ListDialogField field, int index) { String edited = null; if (index != IDX_ADD) { edited = (String) field.getSelectedElements().get(0); } if (index == IDX_ADD || index == IDX_EDIT) { TclCheckContentExcludeInputDialog dialog = new TclCheckContentExcludeInputDialog( getShell(), edited, field.getElements()); if (dialog.open() == Window.OK) { if (edited != null) { field.replaceElement(edited, dialog.getResult()); } else { field.addElement(dialog.getResult()); } } } } private boolean canEdit(List<?> selectedElements) { return selectedElements.size() == 1 && (contributedElements == null || !contributedElements .containsAll(selectedElements)); } @Override public void doubleClicked(ListDialogField field) { if (canEdit(field.getSelectedElements())) { customButtonPressed(field, IDX_EDIT); } } @Override public void selectionChanged(ListDialogField field) { List<?> selectedElements = field.getSelectedElements(); field.enableButton(IDX_EDIT, canEdit(selectedElements)); } @Override public void dialogFieldChanged(DialogField field) { savePatterns((ListDialogField) field); } public void loadPatterns(ListDialogField field) { final List<String> elements = new ArrayList<>(); if (contributedElements != null) { elements.addAll(contributedElements); } final String[] patterns = TextUtils.split(getString(listKey), itemSeparator); if (patterns != null) { elements.addAll(Arrays.asList(patterns)); } field.setElements(elements); selectionChanged(field); } private void savePatterns(ListDialogField field) { final List<?> elements = field.getElements(); if (contributedElements != null) { elements.removeAll(contributedElements); } setString(listKey, TextUtils.join(elements, itemSeparator)); } public void setContributedElements(Set<String> value) { this.contributedElements = value; } } private static class AssociationViwerSorter extends ViewerComparator { private final Set<String> highlighted; public AssociationViwerSorter(Set<String> highlighted) { this.highlighted = highlighted; } @Override public int category(Object element) { return highlighted.contains(element) ? 0 : 1; } } private static class AssociationLabelProvider extends LabelProvider implements IFontProvider { private final Set<String> highlighted; public AssociationLabelProvider(Set<String> highlighted) { this.highlighted = highlighted; } @Override public Font getFont(Object element) { if (highlighted.contains(element)) { return JFaceResources.getFontRegistry() .getBold(JFaceResources.DIALOG_FONT); } return null; } } @Override protected void initialize() { super.initialize(); includeAdapter.loadPatterns(includeDialog); excludeAdapter.loadPatterns(excludeDialog); } @Override public void performDefaults() { super.performDefaults(); includeAdapter.loadPatterns(includeDialog); excludeAdapter.loadPatterns(excludeDialog); } @Override protected boolean saveValues() { final boolean value = super.saveValues(); /* * TODO start job only if associations changed. Listen for * preference change instead? */ new Job(TclPreferencesMessages.TclCorePreferencePage_0) { @Override protected IStatus run(IProgressMonitor monitor) { try { final IScriptProject[] projects = DLTKCore .create(ResourcesPlugin.getWorkspace() .getRoot()) .getScriptProjects(TclNature.NATURE_ID); ResourcesPlugin.getWorkspace().run( new ProjectRefreshOperation(projects), monitor); } catch (CoreException e) { DLTKCore.error( TclPreferencesMessages.TclCorePreferencePage_1, e); } return Status.OK_STATUS; } }.schedule(500); return value; } private static final PreferenceKey[] KEYS = new PreferenceKey[] { new PreferenceKey(TclPlugin.PLUGIN_ID, TclCorePreferences.CHECK_CONTENT_EMPTY_EXTENSION_LOCAL), new PreferenceKey(TclPlugin.PLUGIN_ID, TclCorePreferences.CHECK_CONTENT_EMPTY_EXTENSION_REMOTE), new PreferenceKey(TclPlugin.PLUGIN_ID, TclCorePreferences.CHECK_CONTENT_ANY_EXTENSION_LOCAL), new PreferenceKey(TclPlugin.PLUGIN_ID, TclCorePreferences.CHECK_CONTENT_ANY_EXTENSION_REMOTE), new PreferenceKey(TclPlugin.PLUGIN_ID, TclCorePreferences.CHECK_CONTENT_EXCLUDES), new PreferenceKey(TclPlugin.PLUGIN_ID, DLTKCore.LANGUAGE_FILENAME_ASSOCIATIONS), new PreferenceKey(TclPlugin.PLUGIN_ID, TclSourceElementParser2.class.getName()) }; /** * @param context * @param project * @param allKeys * @param container */ public TclCorePreferenceBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container) { super(context, project, KEYS, container); excludeAdapter = new TclCheckContentAdapter(KEYS[4], TclCorePreferences.CHECK_CONTENT_EXCLUDE_SEPARATOR); includeAdapter = new TclCheckContentAdapter(KEYS[5], DLTKCore.LANGUAGE_FILENAME_ASSOCIATION_SEPARATOR); } /** * @since 2.0 */ @Override protected void validateValuePresenceFor(PreferenceKey key) { if (key.belongsTo(TclPlugin.PLUGIN_ID) && (DLTKCore.LANGUAGE_FILENAME_ASSOCIATIONS .equals(key.getName()) || TclSourceElementParser2.class.getName() .equals(key.getName()))) { return; } super.validateValuePresenceFor(key); } private Button createCheckbox(Composite block, String label, PreferenceKey key) { final Button checkButton = SWTFactory.createCheckButton(block, label); GridData data = new GridData(); data.horizontalIndent = 16; checkButton.setLayoutData(data); bindControl(checkButton, key, null); return checkButton; } private final TclCheckContentAdapter excludeAdapter; private ListDialogField excludeDialog; private final TclCheckContentAdapter includeAdapter; private ListDialogField includeDialog; @Override protected Control createOptionsBlock(Composite parent) { Composite block = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_BOTH); SWTFactory.createLabel(block, TclPreferencesMessages.TclCorePreferencePage_checkContentWithoutExtension, 1); createCheckbox(block, TclPreferencesMessages.TclCorePreferencePage_local, KEYS[0]); createCheckbox(block, TclPreferencesMessages.TclCorePreferencePage_remote, KEYS[1]); SWTFactory.createLabel(block, TclPreferencesMessages.TclCorePreferencePage_checkContentAnyExtension, 1); createCheckbox(block, TclPreferencesMessages.TclCorePreferencePage_local, KEYS[2]); createCheckbox(block, TclPreferencesMessages.TclCorePreferencePage_remote, KEYS[3]); final Composite patternComposite = SWTFactory.createComposite(block, block.getFont(), 1, 1, GridData.FILL_BOTH); final GridLayout patternLayout = new GridLayout(); patternLayout.numColumns = 2; patternLayout.marginHeight = 0; patternLayout.marginWidth = 0; patternComposite.setLayout(patternLayout); final String[] buttons = new String[] { TclPreferencesMessages.TclCorePreferencePage_checkContentAddExclude, TclPreferencesMessages.TclCorePreferencePage_checkContentEditExclude, TclPreferencesMessages.TclCorePreferencePage_checkContentRemoveExclude }; { SWTFactory.createLabel(patternComposite, TclPreferencesMessages.TclCorePreferencePage_Associations, 2); final Set<String> associations = DLTKLanguageManager .loadFilenameAssociations(TclNature.NATURE_ID); includeAdapter.setContributedElements(associations); includeDialog = new ListDialogField(includeAdapter, buttons, new AssociationLabelProvider(associations)) { @Override protected boolean canRemove(ISelection selection) { if (selection instanceof IStructuredSelection) { if (includeAdapter.contributedElements != null) { for (Iterator<?> i = ((IStructuredSelection) selection) .iterator(); i.hasNext();) { final Object element = i.next(); if (includeAdapter.contributedElements .contains(element)) { return false; } } } return true; } return false; } }; includeDialog.setDialogFieldListener(includeAdapter); includeDialog.setRemoveButtonIndex(IDX_REMOVE); includeDialog.setViewerComparator( new AssociationViwerSorter(associations)); final Control listControl = includeDialog .getListControl(patternComposite); final GridData listControlLayoutData = new GridData( GridData.FILL_BOTH); listControlLayoutData.heightHint = new PixelConverter( listControl).convertHeightInCharsToPixels(6); listControl.setLayoutData(listControlLayoutData); includeDialog.getButtonBox(patternComposite).setLayoutData( new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING)); } { SWTFactory.createLabel(patternComposite, TclPreferencesMessages.TclCorePreferencePage_checkContentExcludes, 2); excludeDialog = new ListDialogField(excludeAdapter, buttons, new LabelProvider()); excludeDialog.setDialogFieldListener(excludeAdapter); excludeDialog.setRemoveButtonIndex(IDX_REMOVE); excludeDialog.setViewerComparator(new ViewerComparator()); final Control listControl = excludeDialog .getListControl(patternComposite); final GridData listControlLayoutData = new GridData( GridData.FILL_BOTH); listControlLayoutData.heightHint = new PixelConverter( listControl).convertHeightInCharsToPixels(6); listControl.setLayoutData(listControlLayoutData); excludeDialog.getButtonBox(patternComposite).setLayoutData( new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING)); } return block; } } @Override protected AbstractOptionsBlock createOptionsBlock( IStatusChangeListener newStatusChangedListener, IProject project, IWorkbenchPreferenceContainer container) { return new TclCorePreferenceBlock(newStatusChangedListener, project, container); } @Override protected String getHelpId() { return null; } @Override protected String getProjectHelpId() { return null; } @Override protected String getNatureId() { return TclNature.NATURE_ID; } @Override protected void setDescription() { // empty } @Override protected void setPreferenceStore() { // empty } @Override protected String getPreferencePageId() { return null; } @Override protected String getPropertyPageId() { return null; } }