blob: caa454ed191c1a4e04ccdbc920dbe1e36b5d69ac [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Alex Blewitt <alex.blewitt@gmail.com> - replace new Boolean with Boolean.valueOf - https://bugs.eclipse.org/470344
* Conrad Groth - Bug 213780 - Compare With direction should be configurable
*******************************************************************************/
package org.eclipse.compare.internal;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.IEncodedStreamContentAccessor;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
import org.eclipse.compare.internal.core.ComparePlugin;
import org.eclipse.compare.structuremergeviewer.DiffNode;
import org.eclipse.compare.structuremergeviewer.Differencer;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.preference.RadioGroupFieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
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.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferenceLinkArea;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
public class ComparePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
private static class FakeInput implements ITypedElement, IEncodedStreamContentAccessor {
static final String UTF_16= "UTF-16"; //$NON-NLS-1$
String fContent;
FakeInput(String name) {
fContent= loadPreviewContentFromFile(name);
}
@Override
public Image getImage() {
return null;
}
@Override
public String getName() {
return "no name"; //$NON-NLS-1$
}
@Override
public String getType() {
return "no type"; //$NON-NLS-1$
}
@Override
public InputStream getContents() {
return new ByteArrayInputStream(Utilities.getBytes(fContent, UTF_16));
}
@Override
public String getCharset() {
return UTF_16;
}
private String loadPreviewContentFromFile(String key) {
String preview= Utilities.getString(key);
String separator= System.getProperty("line.separator"); //$NON-NLS-1$
StringBuilder buffer= new StringBuilder();
for (int i= 0; i < preview.length(); i++) {
char c= preview.charAt(i);
if (c == '\n')
buffer.append(separator);
else
buffer.append(c);
}
return buffer.toString();
}
}
private static final String PREFIX= CompareUIPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
public static final String OPEN_STRUCTURE_COMPARE= PREFIX + "OpenStructureCompare"; //$NON-NLS-1$
public static final String USE_OUTLINE_VIEW= PREFIX + "UseOutlineView"; //$NON-NLS-1$
public static final String SYNCHRONIZE_SCROLLING= PREFIX + "SynchronizeScrolling"; //$NON-NLS-1$
public static final String SHOW_PSEUDO_CONFLICTS= PREFIX + "ShowPseudoConflicts"; //$NON-NLS-1$
public static final String INITIALLY_SHOW_ANCESTOR_PANE= PREFIX + "InitiallyShowAncestorPane"; //$NON-NLS-1$
public static final String PREF_SAVE_ALL_EDITORS= PREFIX + "SaveAllEditors"; //$NON-NLS-1$
public static final String IGNORE_WHITESPACE= PREFIX + "IgnoreWhitespace"; //$NON-NLS-1$
//public static final String USE_SPLINES= PREFIX + "UseSplines"; //$NON-NLS-1$
public static final String USE_SINGLE_LINE= PREFIX + "UseSingleLine"; //$NON-NLS-1$
public static final String HIGHLIGHT_TOKEN_CHANGES= PREFIX + "HighlightTokenChanges"; //$NON-NLS-1$
//public static final String USE_RESOLVE_UI= PREFIX + "UseResolveUI"; //$NON-NLS-1$
public static final String CAPPING_DISABLED= PREFIX + "CappingDisable"; //$NON-NLS-1$
public static final String PATH_FILTER= PREFIX + "PathFilter"; //$NON-NLS-1$
public static final String ADDED_LINES_REGEX= PREFIX + "AddedLinesRegex"; //$NON-NLS-1$
public static final String REMOVED_LINES_REGEX= PREFIX + "RemovedLinesRegex"; //$NON-NLS-1$
public static final String SWAPPED = PREFIX + "Swapped"; //$NON-NLS-1$
private IPropertyChangeListener fPreferenceChangeListener;
private List<CompareConfiguration> fCompareConfigurations = new ArrayList<>();
private OverlayPreferenceStore fOverlayStore;
private Map<Button, String> fCheckBoxes = new HashMap<>();
private Text fFilters;
private Text addedLinesRegex;
private Text removedLinesRegex;
private SelectionListener fCheckBoxListener;
public final OverlayPreferenceStore.OverlayKey[] fKeys= new OverlayPreferenceStore.OverlayKey[] {
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, OPEN_STRUCTURE_COMPARE),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, USE_OUTLINE_VIEW),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, SYNCHRONIZE_SCROLLING),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, SHOW_PSEUDO_CONFLICTS),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, INITIALLY_SHOW_ANCESTOR_PANE),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, IGNORE_WHITESPACE),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PREF_SAVE_ALL_EDITORS),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ADDED_LINES_REGEX),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, REMOVED_LINES_REGEX),
//new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, USE_SPLINES),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, USE_SINGLE_LINE),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, HIGHLIGHT_TOKEN_CHANGES),
//new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, USE_RESOLVE_UI),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CAPPING_DISABLED),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PATH_FILTER),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICompareUIConstants.PREF_NAVIGATION_END_ACTION),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, SWAPPED),
};
private List<FieldEditor> editors = new ArrayList<>();
private TabItem fTextCompareTab;
private Button fDisableCappingCheckBox;
public static void initDefaults(IPreferenceStore store) {
store.setDefault(OPEN_STRUCTURE_COMPARE, true);
store.setDefault(USE_OUTLINE_VIEW, false);
store.setDefault(SYNCHRONIZE_SCROLLING, true);
store.setDefault(SHOW_PSEUDO_CONFLICTS, false);
store.setDefault(INITIALLY_SHOW_ANCESTOR_PANE, false);
store.setDefault(IGNORE_WHITESPACE, false);
store.setDefault(PREF_SAVE_ALL_EDITORS, false);
store.setDefault(ADDED_LINES_REGEX, ""); //$NON-NLS-1$
store.setDefault(REMOVED_LINES_REGEX, ""); //$NON-NLS-1$
store.setDefault(USE_SINGLE_LINE, true);
store.setDefault(HIGHLIGHT_TOKEN_CHANGES, true);
store.setDefault(CAPPING_DISABLED, false);
store.setDefault(PATH_FILTER, ""); //$NON-NLS-1$
store.setDefault(ICompareUIConstants.PREF_NAVIGATION_END_ACTION, ICompareUIConstants.PREF_VALUE_PROMPT);
store.setDefault(ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL, ICompareUIConstants.PREF_VALUE_LOOP);
store.setDefault(SWAPPED, false);
}
public ComparePreferencePage() {
setPreferenceStore(CompareUIPlugin.getDefault().getPreferenceStore());
fOverlayStore= new OverlayPreferenceStore(getPreferenceStore(), fKeys);
fPreferenceChangeListener= event -> {
String key= event.getProperty();
if (key.equals(INITIALLY_SHOW_ANCESTOR_PANE)) {
boolean b= fOverlayStore.getBoolean(INITIALLY_SHOW_ANCESTOR_PANE);
for (CompareConfiguration compareConfiguration : fCompareConfigurations) {
compareConfiguration.setProperty(INITIALLY_SHOW_ANCESTOR_PANE, Boolean.valueOf(b));
}
}
};
fOverlayStore.addPropertyChangeListener(fPreferenceChangeListener);
}
@Override
public void init(IWorkbench workbench) {
// empty
}
@Override
public boolean performOk() {
fOverlayStore.setValue(ADDED_LINES_REGEX, addedLinesRegex.getText());
fOverlayStore.setValue(REMOVED_LINES_REGEX, removedLinesRegex.getText());
editors.forEach(FieldEditor::store);
fOverlayStore.propagate();
ComparePlugin.getDefault().setCappingDisabled(
getPreferenceStore().getBoolean(
ComparePreferencePage.CAPPING_DISABLED));
return true;
}
@Override
protected void performDefaults() {
fOverlayStore.loadDefaults();
initializeFields();
super.performDefaults();
}
@Override
public void dispose() {
if (fOverlayStore != null) {
if (fPreferenceChangeListener != null) {
fOverlayStore.removePropertyChangeListener(fPreferenceChangeListener);
fPreferenceChangeListener= null;
}
fOverlayStore.stop();
fOverlayStore= null;
}
super.dispose();
}
public static boolean getSaveAllEditors() {
IPreferenceStore store= CompareUIPlugin.getDefault().getPreferenceStore();
return store.getBoolean(PREF_SAVE_ALL_EDITORS);
}
public static void setSaveAllEditors(boolean value) {
IPreferenceStore store= CompareUIPlugin.getDefault().getPreferenceStore();
store.setValue(PREF_SAVE_ALL_EDITORS, value);
}
@Override
protected Control createContents(Composite parent) {
if (PlatformUI.isWorkbenchRunning()) {
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, ICompareContextIds.COMPARE_PREFERENCE_PAGE);
}
fOverlayStore.load();
fOverlayStore.start();
TabFolder folder= new TabFolder(parent, SWT.NONE);
folder.setLayout(new TabFolderLayout());
folder.setLayoutData(new GridData(GridData.FILL_BOTH));
TabItem item= new TabItem(folder, SWT.NONE);
item.setText(Utilities.getString("ComparePreferencePage.generalTab.label")); //$NON-NLS-1$
item.setControl(createGeneralPage(folder));
item= new TabItem(folder, SWT.NONE);
item.setText(Utilities.getString("ComparePreferencePage.textCompareTab.label")); //$NON-NLS-1$
item.setControl(createTextComparePage(folder));
fTextCompareTab = item;
initializeFields();
Dialog.applyDialogFont(folder);
return folder;
}
private Control createGeneralPage(Composite parent) {
Composite composite= new Composite(parent, SWT.NULL);
GridLayout layout= new GridLayout();
layout.numColumns= 1;
composite.setLayout(layout);
addCheckBox(composite, "ComparePreferencePage.structureCompare.label", OPEN_STRUCTURE_COMPARE, 0); //$NON-NLS-1$
addCheckBox(composite, "ComparePreferencePage.structureOutline.label", USE_OUTLINE_VIEW, 0); //$NON-NLS-1$
addCheckBox(composite, "ComparePreferencePage.ignoreWhitespace.label", IGNORE_WHITESPACE, 0); //$NON-NLS-1$
// a spacer
new Label(composite, SWT.NONE);
addCheckBox(composite, "ComparePreferencePage.saveBeforePatching.label", PREF_SAVE_ALL_EDITORS, 0); //$NON-NLS-1$
// a spacer
new Label(composite, SWT.NONE);
Label l= new Label(composite, SWT.WRAP);
l.setText(Utilities.getString("ComparePreferencePage.regex.description")); //$NON-NLS-1$
Composite c2= new Composite(composite, SWT.NONE);
c2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
layout= new GridLayout(2, false);
layout.marginWidth= 0;
c2.setLayout(layout);
l= new Label(c2, SWT.NONE);
l.setText(Utilities.getString("ComparePreferencePage.regexAdded.label")); //$NON-NLS-1$
addedLinesRegex = new Text(c2, SWT.BORDER);
addedLinesRegex.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
addedLinesRegex.setText(fOverlayStore.getString(ADDED_LINES_REGEX));
l= new Label(c2, SWT.NONE);
l.setText(Utilities.getString("ComparePreferencePage.regexRemoved.label")); //$NON-NLS-1$
removedLinesRegex = new Text(c2, SWT.BORDER);
removedLinesRegex.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
removedLinesRegex.setText(fOverlayStore.getString(REMOVED_LINES_REGEX));
// a spacer
new Label(composite, SWT.NONE);
l= new Label(composite, SWT.WRAP);
l.setText(Utilities.getString("ComparePreferencePage.filter.description")); //$NON-NLS-1$
Composite c3= new Composite(composite, SWT.NONE);
c3.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
layout= new GridLayout(2, false);
layout.marginWidth= 0;
c3.setLayout(layout);
l= new Label(c3, SWT.NONE);
l.setText(Utilities.getString("ComparePreferencePage.filter.label")); //$NON-NLS-1$
fFilters= new Text(c3, SWT.BORDER);
fFilters.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fFilters.setText(fOverlayStore.getString(PATH_FILTER));
fFilters.addModifyListener(
e -> {
String filters= fFilters.getText();
String message= CompareResourceFilter.validateResourceFilters(filters);
setValid(message == null);
setMessage(null);
setErrorMessage(message);
fOverlayStore.setValue(PATH_FILTER, filters);
}
);
return composite;
}
private Control createTextComparePage(Composite parent) {
Composite composite= new Composite(parent, SWT.NULL);
GridLayout layout= new GridLayout();
layout.numColumns= 1;
composite.setLayout(layout);
addCheckBox(composite, "ComparePreferencePage.synchronizeScrolling.label", SYNCHRONIZE_SCROLLING, 0); //$NON-NLS-1$
addCheckBox(composite, "ComparePreferencePage.initiallyShowAncestorPane.label", INITIALLY_SHOW_ANCESTOR_PANE, 0); //$NON-NLS-1$
addCheckBox(composite, "ComparePreferencePage.showPseudoConflicts.label", SHOW_PSEUDO_CONFLICTS, 0); //$NON-NLS-1$
//addCheckBox(composite, "ComparePreferencePage.useSplines.label", USE_SPLINES, 0); //$NON-NLS-1$
addCheckBox(composite, "ComparePreferencePage.useSingleLine.label", USE_SINGLE_LINE, 0); //$NON-NLS-1$
addCheckBox(composite, "ComparePreferencePage.highlightTokenChanges.label", HIGHLIGHT_TOKEN_CHANGES, 0); //$NON-NLS-1$
//addCheckBox(composite, "ComparePreferencePage.useResolveUI.label", USE_RESOLVE_UI, 0); //$NON-NLS-1$
fDisableCappingCheckBox = addCheckBox(composite, "ComparePreferencePage.disableCapping.label", CAPPING_DISABLED, 0); //$NON-NLS-1$
addCheckBox(composite, "ComparePreferencePage.swapped.label", SWAPPED, 0); //$NON-NLS-1$
Composite radioGroup = new Composite(composite, SWT.NULL);
radioGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
RadioGroupFieldEditor editor = new RadioGroupFieldEditor(
ICompareUIConstants.PREF_NAVIGATION_END_ACTION,
CompareMessages.ComparePreferencePage_0, 1,
new String[][] {
new String[] { CompareMessages.ComparePreferencePage_1, ICompareUIConstants.PREF_VALUE_PROMPT },
new String[] { CompareMessages.ComparePreferencePage_2, ICompareUIConstants.PREF_VALUE_LOOP },
new String[] { CompareMessages.ComparePreferencePage_3, ICompareUIConstants.PREF_VALUE_NEXT },
new String[] { CompareMessages.ComparePreferencePage_4, ICompareUIConstants.PREF_VALUE_DO_NOTHING}
},
radioGroup, true);
editor.setPreferenceStore(fOverlayStore);
editor.fillIntoGrid(radioGroup, 1);
editors.add(editor);
PreferenceLinkArea area = new PreferenceLinkArea(composite, SWT.NONE,
"org.eclipse.ui.preferencePages.ColorsAndFonts", //$NON-NLS-1$
Utilities.getString("ComparePreferencePage.colorAndFontLink"), //$NON-NLS-1$
(IWorkbenchPreferenceContainer) getContainer(),
"selectCategory:org.eclipse.compare.contentmergeviewer.TextMergeViewer"); //$NON-NLS-1$
GridData data = new GridData(SWT.FILL, SWT.CENTER, false, false);
area.getControl().setLayoutData(data);
// a spacer
Label separator= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
separator.setVisible(false);
{
Label previewLabel = new Label(composite, SWT.NULL);
previewLabel.setText(Utilities.getString("ComparePreferencePage.preview-2way.label")); //$NON-NLS-1$
Control previewer = create2WayPreviewer(composite);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.widthHint = convertWidthInCharsToPixels(60);
gd.heightHint = convertHeightInCharsToPixels(12);
previewer.setLayoutData(gd);
}
{
Label previewLabel = new Label(composite, SWT.NULL);
previewLabel.setText(Utilities.getString("ComparePreferencePage.preview.label")); //$NON-NLS-1$
Control previewer = create3WayPreviewer(composite);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.widthHint = convertWidthInCharsToPixels(60);
gd.heightHint = convertHeightInCharsToPixels(9);
previewer.setLayoutData(gd);
}
return composite;
}
private Control create3WayPreviewer(Composite parent) {
CompareConfiguration compareConfiguration = new CompareConfiguration(fOverlayStore);
compareConfiguration.setAncestorLabel(Utilities.getString("ComparePreferencePage.ancestor.label")); //$NON-NLS-1$
compareConfiguration.setLeftLabel(Utilities.getString("ComparePreferencePage.left.label")); //$NON-NLS-1$
compareConfiguration.setLeftEditable(false);
compareConfiguration.setRightLabel(Utilities.getString("ComparePreferencePage.right.label")); //$NON-NLS-1$
compareConfiguration.setRightEditable(false);
TextMergeViewer previewViewer = new TextMergeViewer(parent, SWT.BORDER, compareConfiguration);
previewViewer.setInput(
new DiffNode(Differencer.CONFLICTING,
new FakeInput("ComparePreferencePage.previewAncestor"), //$NON-NLS-1$
new FakeInput("ComparePreferencePage.previewLeft"), //$NON-NLS-1$
new FakeInput("ComparePreferencePage.previewRight") //$NON-NLS-1$
)
);
Control c = previewViewer.getControl();
c.addDisposeListener(e -> {
if (compareConfiguration != null)
compareConfiguration.dispose();
});
fCompareConfigurations.add(compareConfiguration);
return c;
}
private Control create2WayPreviewer(Composite parent) {
CompareConfiguration compareConfiguration = new CompareConfiguration(fOverlayStore);
compareConfiguration.setLeftLabel(Utilities.getString("ComparePreferencePage.workingCopy.label")); //$NON-NLS-1$
compareConfiguration.setRightLabel(Utilities.getString("ComparePreferencePage.baseline.label")); //$NON-NLS-1$
compareConfiguration.setRightEditable(false);
TextMergeViewer previewViewer = new TextMergeViewer(parent, SWT.BORDER, compareConfiguration);
previewViewer.setInput(new DiffNode(
new FakeInput("ComparePreferencePage.workingCopy"), //$NON-NLS-1$
new FakeInput("ComparePreferencePage.baseline") //$NON-NLS-1$
));
Control c = previewViewer.getControl();
c.addDisposeListener(e -> {
if (compareConfiguration != null)
compareConfiguration.dispose();
});
fCompareConfigurations.add(compareConfiguration);
return c;
}
private void initializeFields() {
Iterator<Button> e = fCheckBoxes.keySet().iterator();
while (e.hasNext()) {
Button b = e.next();
String key= fCheckBoxes.get(b);
b.setSelection(fOverlayStore.getBoolean(key));
}
if (fFilters != null)
fFilters.setText(fOverlayStore.getString(PATH_FILTER));
if (addedLinesRegex != null)
addedLinesRegex.setText(fOverlayStore.getString(ADDED_LINES_REGEX));
if (removedLinesRegex != null)
removedLinesRegex.setText(fOverlayStore.getString(REMOVED_LINES_REGEX));
editors.forEach(FieldEditor::load);
}
// overlay stuff
private Button addCheckBox(Composite parent, String labelKey, String key, int indentation) {
String label= Utilities.getString(labelKey);
Button checkBox= new Button(parent, SWT.CHECK);
checkBox.setText(label);
GridData gd= new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalIndent= indentation;
checkBox.setLayoutData(gd);
if (fCheckBoxListener == null) {
fCheckBoxListener= new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Button button= (Button) e.widget;
fOverlayStore.setValue(fCheckBoxes.get(button), button.getSelection());
}
};
}
checkBox.addSelectionListener(fCheckBoxListener);
fCheckBoxes.put(checkBox, key);
return checkBox;
}
@Override
public void applyData(Object data) {
if (ComparePreferencePage.CAPPING_DISABLED.equals(data)) {
fTextCompareTab.getParent().setSelection(fTextCompareTab);
fDisableCappingCheckBox.setFocus();
}
}
}