/*******************************************************************************
* Copyright (c) 2000, 2012 IBM Corporation and others.
* Copyright (C) 2009, Tor Arne Vestbø <torarnv@gmail.com>
* Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
*
* 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
*******************************************************************************/
package org.eclipse.egit.ui.internal.preferences;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import org.eclipse.core.resources.IResource;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.internal.GitLabelProvider;
import org.eclipse.egit.ui.internal.SWTUtils;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator.DecorationHelper;
import org.eclipse.egit.ui.internal.decorators.DecorationResult;
import org.eclipse.egit.ui.internal.decorators.IDecoratableResource;
import org.eclipse.egit.ui.internal.decorators.IDecoratableResource.Staged;
import org.eclipse.egit.ui.internal.synchronize.mapping.GitChangeSetLabelProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.preference.PreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.DecorationOverlayIcon;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
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.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.swt.widgets.TreeItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.eclipse.ui.ide.IDE.SharedImages;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
/**
* Preference page for customizing Git label decorations
*/
public class GitDecoratorPreferencePage extends PreferencePage implements
IWorkbenchPreferencePage {
private GeneralTab generalTab;
private TextDecorationTab textDecorationTab;
private IconDecorationTab iconDecorationTab;
private OtherDecorationTab otherDecorationTab;
private Preview navigatorPreview;
private Preview changeSetPreview;
private boolean tabsInitialized;
private static final Collection PREVIEW_FILESYSTEM_ROOT;
private static final Map<String, String> FILE_AND_FOLDER_BINDINGS;
private static final Map<String, String> PROJECT_BINDINGS;
private static final Map<String, String> CHANGESET_LABEL_BINDINGS;
private static IPropertyChangeListener themeListener;
static {
final PreviewResource project = new PreviewResource(
"Project", IResource.PROJECT, "repository" + '|' + RepositoryState.MERGING.getDescription(), "master", "↑2 ↓1", true, false, true, Staged.NOT_STAGED, false, false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
final ArrayList<PreviewResource> children = new ArrayList<PreviewResource>();
children
.add(new PreviewResource(
"folder", IResource.FOLDER, "repository", null, null, true, false, true, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"tracked.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"untracked.txt", IResource.FILE, "repository", null, null, false, false, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"ignored.txt", IResource.FILE, "repository", null, null, false, true, false, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"dirty.txt", IResource.FILE, "repository", null, null, true, false, true, Staged.NOT_STAGED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"staged.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.MODIFIED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"partially-staged.txt", IResource.FILE, "repository", null, null, true, false, true, Staged.MODIFIED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"added.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.ADDED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"removed.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.REMOVED, false, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"conflict.txt", IResource.FILE, "repository", null, null, true, false, true, Staged.NOT_STAGED, true, false)); //$NON-NLS-1$ //$NON-NLS-2$
children
.add(new PreviewResource(
"assume-valid.txt", IResource.FILE, "repository", null, null, true, false, false, Staged.NOT_STAGED, false, true)); //$NON-NLS-1$ //$NON-NLS-2$
project.children = children;
PREVIEW_FILESYSTEM_ROOT = Collections.singleton(project);
FILE_AND_FOLDER_BINDINGS = new HashMap<String, String>();
FILE_AND_FOLDER_BINDINGS.put(DecorationHelper.BINDING_RESOURCE_NAME,
UIText.DecoratorPreferencesPage_bindingResourceName);
FILE_AND_FOLDER_BINDINGS.put(DecorationHelper.BINDING_DIRTY_FLAG,
UIText.DecoratorPreferencesPage_bindingDirtyFlag);
FILE_AND_FOLDER_BINDINGS.put(DecorationHelper.BINDING_STAGED_FLAG,
UIText.DecoratorPreferencesPage_bindingStagedFlag);
PROJECT_BINDINGS = new HashMap<String, String>();
PROJECT_BINDINGS.put(DecorationHelper.BINDING_RESOURCE_NAME,
UIText.DecoratorPreferencesPage_bindingResourceName);
PROJECT_BINDINGS.put(DecorationHelper.BINDING_DIRTY_FLAG,
UIText.DecoratorPreferencesPage_bindingDirtyFlag);
PROJECT_BINDINGS.put(DecorationHelper.BINDING_STAGED_FLAG,
UIText.DecoratorPreferencesPage_bindingStagedFlag);
PROJECT_BINDINGS.put(DecorationHelper.BINDING_REPOSITORY_NAME,
UIText.GitDecoratorPreferencePage_bindingRepositoryNameFlag);
PROJECT_BINDINGS.put(DecorationHelper.BINDING_BRANCH_NAME,
UIText.DecoratorPreferencesPage_bindingBranchName);
PROJECT_BINDINGS.put(DecorationHelper.BINDING_BRANCH_STATUS,
UIText.DecoratorPreferencesPage_bindingBranchStatus);
CHANGESET_LABEL_BINDINGS = new HashMap<String, String>();
CHANGESET_LABEL_BINDINGS.put(removeBraces(GitChangeSetLabelProvider.BINDING_CHANGESET_AUTHOR),
UIText.DecoratorPreferencesPage_bindingChangeSetAuthor);
CHANGESET_LABEL_BINDINGS.put(removeBraces(GitChangeSetLabelProvider.BINDING_CHANGESET_DATE),
UIText.DecoratorPreferencesPage_bindingChangeSetDate);
CHANGESET_LABEL_BINDINGS.put(removeBraces(GitChangeSetLabelProvider.BINDING_CHANGESET_COMMITTER),
UIText.DecoratorPreferencesPage_bindingChangeSetCommitter);
CHANGESET_LABEL_BINDINGS.put(removeBraces(GitChangeSetLabelProvider.BINDING_CHANGESET_SHORT_MESSAGE),
UIText.DecoratorPreferencesPage_bindingChangeSetShortMessage);
}
private static String removeBraces(String string) {
return string.replaceAll("[}{]", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* @see PreferencePage#createContents(Composite)
*/
protected Control createContents(Composite parent) {
Composite composite = SWTUtils.createHVFillComposite(parent,
SWTUtils.MARGINS_NONE);
SWTUtils.createLabel(composite, UIText.DecoratorPreferencesPage_description);
Composite folderComposite = SWTUtils.createHFillComposite(composite,
SWTUtils.MARGINS_NONE);
TabFolder tabFolder = new TabFolder(folderComposite, SWT.NONE);
tabFolder.setLayoutData(SWTUtils.createHVFillGridData());
tabFolder.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (navigatorPreview != null && changeSetPreview != null) {
if (UIText.DecoratorPreferencesPage_otherDecorations.equals(e.item.getData())) {
navigatorPreview.hide();
changeSetPreview.show();
} else {
changeSetPreview.hide();
navigatorPreview.show();
}
}
}
});
changeSetPreview = new ChangeSetPreview(composite);
navigatorPreview = new NavigatorPreview(composite);
generalTab = new GeneralTab(tabFolder);
textDecorationTab = new TextDecorationTab(tabFolder);
iconDecorationTab = new IconDecorationTab(tabFolder);
otherDecorationTab = new OtherDecorationTab(tabFolder);
initializeValues();
changeSetPreview.hide();
changeSetPreview.refresh();
navigatorPreview.refresh();
generalTab.addObserver(navigatorPreview);
textDecorationTab.addObserver(navigatorPreview);
iconDecorationTab.addObserver(navigatorPreview);
otherDecorationTab.addObserver(changeSetPreview);
// TODO: Add help text for this preference page
themeListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
navigatorPreview.refresh();
changeSetPreview.refresh();
}
};
PlatformUI.getWorkbench().getThemeManager().addPropertyChangeListener(
themeListener);
Dialog.applyDialogFont(parent);
return tabFolder;
}
/**
* Wrapper class for TabItems used in the preference page TabFolder
*
* The reason for this wrapper is mainly that the class TabItem is not
* supposed to be subclassed.
*
* When controls in the tab change it will emit update() to any registered
* observers. This is currently used for updating the decoration preview.
*/
private abstract class Tab extends Observable {
public abstract void initializeValues(IPreferenceStore store);
public abstract void performDefaults(IPreferenceStore store);
public abstract void performOk(IPreferenceStore store);
}
/**
* Tab page for general preferences related to decoration
*/
private class GeneralTab extends Tab implements SelectionListener {
private Button recomputeAncestorDecorations;
public GeneralTab(TabFolder parent) {
Composite composite = SWTUtils.createHVFillComposite(parent,
SWTUtils.MARGINS_DEFAULT, 1);
recomputeAncestorDecorations = SWTUtils
.createCheckBox(
composite,
UIText.DecoratorPreferencesPage_recomputeAncestorDecorations);
recomputeAncestorDecorations
.setToolTipText(UIText.DecoratorPreferencesPage_recomputeAncestorDecorationsTooltip);
SWTUtils.createPreferenceLink(
(IWorkbenchPreferenceContainer) getContainer(), composite,
"org.eclipse.ui.preferencePages.Decorators", //$NON-NLS-1$
UIText.DecoratorPreferencesPage_labelDecorationsLink);
SWTUtils.createPreferenceLink(
(IWorkbenchPreferenceContainer) getContainer(), composite,
"org.eclipse.ui.preferencePages.ColorsAndFonts", //$NON-NLS-1$
UIText.DecoratorPreferencesPage_colorsAndFontsLink);
recomputeAncestorDecorations.addSelectionListener(this);
final TabItem tabItem = new TabItem(parent, SWT.NONE);
tabItem.setText(UIText.DecoratorPreferencesPage_generalTabFolder);
tabItem.setControl(composite);
}
public void initializeValues(IPreferenceStore store) {
recomputeAncestorDecorations.setSelection(store
.getBoolean(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS));
}
public void performDefaults(IPreferenceStore store) {
recomputeAncestorDecorations
.setSelection(store
.getDefaultBoolean(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS));
}
public void performOk(IPreferenceStore store) {
store.setValue(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS,
recomputeAncestorDecorations.getSelection());
}
public void widgetSelected(SelectionEvent e) {
setChanged();
notifyObservers();
}
public void widgetDefaultSelected(SelectionEvent e) {
// Not interesting for us
}
}
/**
* The tab page for text-decoration preferences
*/
private class TextDecorationTab extends Tab implements ModifyListener {
private final FormatEditor fileTextFormat;
private final FormatEditor folderTextFormat;
private final FormatEditor projectTextFormat;
public TextDecorationTab(TabFolder parent) {
Composite composite = SWTUtils.createHVFillComposite(parent,
SWTUtils.MARGINS_DEFAULT, 3);
fileTextFormat = new FormatEditor(composite,
UIText.DecoratorPreferencesPage_fileFormatLabel,
UIText.DecoratorPreferencesPage_addVariablesAction,
FILE_AND_FOLDER_BINDINGS,
UIPreferences.DECORATOR_FILETEXT_DECORATION);
folderTextFormat = new FormatEditor(composite,
UIText.DecoratorPreferencesPage_folderFormatLabel,
UIText.DecoratorPreferencesPage_addVariablesAction2,
FILE_AND_FOLDER_BINDINGS,
UIPreferences.DECORATOR_FOLDERTEXT_DECORATION);
projectTextFormat = new FormatEditor(composite,
UIText.DecoratorPreferencesPage_projectFormatLabel,
UIText.DecoratorPreferencesPage_addVariablesAction3,
PROJECT_BINDINGS,
UIPreferences.DECORATOR_PROJECTTEXT_DECORATION);
fileTextFormat.addModifyListener(this);
folderTextFormat.addModifyListener(this);
projectTextFormat.addModifyListener(this);
final TabItem tabItem = new TabItem(parent, SWT.NONE);
tabItem.setText(UIText.DecoratorPreferencesPage_textLabel);
tabItem.setControl(composite);
}
public void initializeValues(IPreferenceStore store) {
fileTextFormat.initializeValue(store);
folderTextFormat.initializeValue(store);
projectTextFormat.initializeValue(store);
}
public void performDefaults(IPreferenceStore store) {
fileTextFormat.performDefaults(store);
folderTextFormat.performDefaults(store);
projectTextFormat.performDefaults(store);
}
public void performOk(IPreferenceStore store) {
fileTextFormat.performOk(store);
folderTextFormat.performOk(store);
projectTextFormat.performOk(store);
}
public void modifyText(ModifyEvent e) {
setChanged();
notifyObservers();
}
}
private class OtherDecorationTab extends Tab implements ModifyListener {
private final FormatEditor changeSetLabelFormat;
private final Text dateFormat;
private final Label dateFormatPreview;
private final Date exampleDate = new Date();
private boolean formatValid;
public OtherDecorationTab(TabFolder parent) {
Composite composite = SWTUtils.createHVFillComposite(parent,
SWTUtils.MARGINS_DEFAULT, 3);
changeSetLabelFormat = new FormatEditor(composite,
UIText.DecoratorPreferencesPage_changeSetLabelFormat,
UIText.DecoratorPreferencesPage_addVariablesAction3,
CHANGESET_LABEL_BINDINGS,
UIPreferences.SYNC_VIEW_CHANGESET_LABEL_FORMAT);
final TabItem tabItem = new TabItem(parent, SWT.NONE);
Label dfLabel = SWTUtils.createLabel(composite, UIText.DecoratorPreferencesPage_dateFormat);
dfLabel.setLayoutData(SWTUtils.createGridData(SWT.DEFAULT,
SWT.DEFAULT, false, false));
dateFormat = SWTUtils.createText(composite, 2);
Label dpLabel = SWTUtils.createLabel(composite, UIText.DecoratorPreferencesPage_dateFormatPreview);
dpLabel.setLayoutData(SWTUtils.createGridData(SWT.DEFAULT,
SWT.DEFAULT, false, false));
dateFormatPreview = SWTUtils.createLabel(composite, null, 2);
tabItem.setText(UIText.DecoratorPreferencesPage_otherDecorations);
tabItem.setControl(composite);
tabItem.setData(UIText.DecoratorPreferencesPage_otherDecorations);
changeSetLabelFormat.addModifyListener(this);
dateFormat.addModifyListener(this);
}
private void updateDateFormatPreview() {
SimpleDateFormat sdf;
try {
sdf = new SimpleDateFormat(dateFormat.getText());
dateFormatPreview.setText(sdf.format(exampleDate));
formatValid = true;
} catch (Exception ex) {
dateFormatPreview.setText(UIText.DecoratorPreferencesPage_wrongDateFormat);
formatValid = false;
}
}
public void initializeValues(IPreferenceStore store) {
changeSetLabelFormat.initializeValue(store);
dateFormat.setText(store.getString(UIPreferences.DATE_FORMAT));
}
public void performDefaults(IPreferenceStore store) {
changeSetLabelFormat.performDefaults(store);
dateFormat.setText(store.getDefaultString(UIPreferences.DATE_FORMAT));
}
public void performOk(IPreferenceStore store) {
changeSetLabelFormat.performOk(store);
if (formatValid) {
store.setValue(UIPreferences.DATE_FORMAT, dateFormat.getText());
}
}
public void modifyText(ModifyEvent e) {
updateDateFormatPreview();
setChanged();
notifyObservers();
}
}
private static final class FormatEditor extends SelectionAdapter {
private final Text text;
private final Map bindings;
private final String key;
public FormatEditor(Composite composite, String title,
String buttonText, Map bindings, String key) {
this.key = key;
this.bindings = bindings;
final Label label = SWTUtils.createLabel(composite, title);
label.setLayoutData(SWTUtils.createGridData(SWT.DEFAULT,
SWT.DEFAULT, false, false));
text = SWTUtils.createText(composite);
final Button button = new Button(composite, SWT.NONE);
button.setText(buttonText);
button.setLayoutData(new GridData());
button.addSelectionListener(this);
}
public void addModifyListener(ModifyListener listener) {
text.addModifyListener(listener);
}
public void widgetSelected(SelectionEvent e) {
final ILabelProvider labelProvider = new LabelProvider() {
public String getText(Object element) {
return ((Map.Entry) element).getKey()
+ " - " + ((Map.Entry) element).getValue(); //$NON-NLS-1$
}
};
final IStructuredContentProvider contentsProvider = ArrayContentProvider.getInstance();
final ListSelectionDialog dialog = new ListSelectionDialog(text
.getShell(), bindings.entrySet(), contentsProvider,
labelProvider,
UIText.DecoratorPreferencesPage_selectVariablesToAdd);
dialog.setHelpAvailable(false);
dialog
.setTitle(UIText.DecoratorPreferencesPage_addVariablesTitle);
if (dialog.open() != Window.OK)
return;
Object[] result = dialog.getResult();
for (int i = 0; i < result.length; i++) {
text.insert("{" + ((Map.Entry) result[i]).getKey() + "}"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public void performOk(IPreferenceStore store) {
store.setValue(key, text.getText());
}
public void performDefaults(IPreferenceStore store) {
store.setToDefault(key);
text.setText(store.getDefaultString(key));
}
public void initializeValue(IPreferenceStore store) {
text.setText(store.getString(key));
}
}
/**
* Tab page for icon-related preferences
*/
private class IconDecorationTab extends Tab implements SelectionListener {
private Button showTracked;
private Button showUntracked;
private Button showStaged;
private Button showConflicts;
private Button showAssumeValid;
private Button showDirty;
public IconDecorationTab(TabFolder parent) {
Composite composite = SWTUtils.createHVFillComposite(parent,
SWTUtils.MARGINS_DEFAULT, 2);
showTracked = SWTUtils.createCheckBox(composite,
UIText.DecoratorPreferencesPage_iconsShowTracked);
showUntracked = SWTUtils.createCheckBox(composite,
UIText.DecoratorPreferencesPage_iconsShowUntracked);
showStaged = SWTUtils.createCheckBox(composite,
UIText.DecoratorPreferencesPage_iconsShowStaged);
showConflicts = SWTUtils.createCheckBox(composite,
UIText.DecoratorPreferencesPage_iconsShowConflicts);
showAssumeValid = SWTUtils.createCheckBox(composite,
UIText.DecoratorPreferencesPage_iconsShowAssumeValid);
showDirty = SWTUtils.createCheckBox(composite,
UIText.GitDecoratorPreferencePage_iconsShowDirty);
showTracked.addSelectionListener(this);
showUntracked.addSelectionListener(this);
showStaged.addSelectionListener(this);
showConflicts.addSelectionListener(this);
showAssumeValid.addSelectionListener(this);
showDirty.addSelectionListener(this);
final TabItem tabItem = new TabItem(parent, SWT.NONE);
tabItem.setText(UIText.DecoratorPreferencesPage_iconLabel);
tabItem.setControl(composite);
}
public void initializeValues(IPreferenceStore store) {
showTracked.setSelection(store
.getBoolean(UIPreferences.DECORATOR_SHOW_TRACKED_ICON));
showUntracked.setSelection(store
.getBoolean(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON));
showStaged.setSelection(store
.getBoolean(UIPreferences.DECORATOR_SHOW_STAGED_ICON));
showConflicts.setSelection(store
.getBoolean(UIPreferences.DECORATOR_SHOW_CONFLICTS_ICON));
showAssumeValid
.setSelection(store
.getBoolean(UIPreferences.DECORATOR_SHOW_ASSUME_VALID_ICON));
showDirty.setSelection(store
.getBoolean(UIPreferences.DECORATOR_SHOW_DIRTY_ICON));
}
public void performDefaults(IPreferenceStore store) {
showTracked
.setSelection(store
.getDefaultBoolean(UIPreferences.DECORATOR_SHOW_TRACKED_ICON));
showUntracked
.setSelection(store
.getDefaultBoolean(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON));
showStaged
.setSelection(store
.getDefaultBoolean(UIPreferences.DECORATOR_SHOW_STAGED_ICON));
showConflicts
.setSelection(store
.getDefaultBoolean(UIPreferences.DECORATOR_SHOW_CONFLICTS_ICON));
showAssumeValid
.setSelection(store
.getDefaultBoolean(UIPreferences.DECORATOR_SHOW_ASSUME_VALID_ICON));
showDirty
.setSelection(store
.getDefaultBoolean(UIPreferences.DECORATOR_SHOW_DIRTY_ICON));
}
public void performOk(IPreferenceStore store) {
store.setValue(UIPreferences.DECORATOR_SHOW_TRACKED_ICON,
showTracked.getSelection());
store.setValue(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON,
showUntracked.getSelection());
store.setValue(UIPreferences.DECORATOR_SHOW_STAGED_ICON, showStaged
.getSelection());
store.setValue(UIPreferences.DECORATOR_SHOW_CONFLICTS_ICON,
showConflicts.getSelection());
store.setValue(UIPreferences.DECORATOR_SHOW_ASSUME_VALID_ICON,
showAssumeValid.getSelection());
store.setValue(UIPreferences.DECORATOR_SHOW_DIRTY_ICON,
showDirty.getSelection());
}
public void widgetSelected(SelectionEvent e) {
setChanged();
notifyObservers();
}
public void widgetDefaultSelected(SelectionEvent e) {
// Not interesting for us
}
}
/**
* Initializes states of the controls from the preference store.
*/
private void initializeValues() {
final IPreferenceStore store = getPreferenceStore();
generalTab.initializeValues(store);
textDecorationTab.initializeValues(store);
iconDecorationTab.initializeValues(store);
otherDecorationTab.initializeValues(store);
setValid(true);
tabsInitialized = true;
}
/**
* @see IWorkbenchPreferencePage#init(IWorkbench)
*/
public void init(IWorkbench workbench) {
// No-op
}
/**
* OK was clicked. Store the preferences to the plugin store
*
* @return whether it is okay to close the preference page
*/
public boolean performOk() {
IPreferenceStore store = getPreferenceStore();
final boolean okToClose = performOk(store);
if (store.needsSaving()) {
try {
((IPersistentPreferenceStore)store).save();
Activator.broadcastPropertyChange(new PropertyChangeEvent(this,
Activator.DECORATORS_CHANGED, null, null));
} catch (IOException e) {
Activator.handleError(e.getMessage(), e, true);
}
}
return okToClose;
}
/**
* Store the preferences to the given preference store
*
* @param store
* the preference store to store the preferences to
*
* @return whether it operation succeeded
*/
private boolean performOk(IPreferenceStore store) {
generalTab.performOk(store);
textDecorationTab.performOk(store);
iconDecorationTab.performOk(store);
otherDecorationTab.performOk(store);
return true;
}
/**
* Defaults was clicked. Restore the Git decoration preferences to their
* default values
*/
protected void performDefaults() {
IPreferenceStore store = getPreferenceStore();
generalTab.performDefaults(store);
textDecorationTab.performDefaults(store);
iconDecorationTab.performDefaults(store);
otherDecorationTab.performDefaults(store);
super.performDefaults();
navigatorPreview.refresh();
changeSetPreview.refresh();
}
/**
* Returns the preference store that belongs to our plugin.
*
* This is important because we want to store our preferences separately
* from the desktop.
*
* @return the preference store for this plugin
*/
protected IPreferenceStore doGetPreferenceStore() {
return Activator.getDefault().getPreferenceStore();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.DialogPage#dispose()
*/
public void dispose() {
PlatformUI.getWorkbench().getThemeManager()
.removePropertyChangeListener(themeListener);
super.dispose();
}
private abstract class Preview
implements Observer {
protected PreferenceStore store = new PreferenceStore();
protected final TreeViewer fViewer;
private Composite composite;
private Composite parent;
protected final ResourceManager fImageCache = new LocalResourceManager(
JFaceResources.getResources());
public Preview(Composite parent) {
this.parent = parent;
composite = SWTUtils.createHVFillComposite(parent, SWTUtils.MARGINS_NONE);
SWTUtils.createLabel(composite, UIText.DecoratorPreferencesPage_preview);
fViewer = new TreeViewer(composite);
fViewer.getControl().setLayoutData(SWTUtils.createHVFillGridData());
}
public void update(Observable o, Object arg) {
refresh();
}
public abstract void refresh();
public void dispose() {
fImageCache.dispose();
}
public void hide() {
((GridData)composite.getLayoutData()).exclude = true; // ignore by layout
composite.setVisible(false);
composite.layout();
parent.layout();
}
public void show() {
((GridData)composite.getLayoutData()).exclude = false; // ignore by layout
composite.setVisible(true);
composite.layout();
parent.layout();
}
}
private class ChangeSetPreview extends Preview implements
ITreeContentProvider {
public ChangeSetPreview(Composite composite) {
super(composite);
fViewer.setContentProvider(this);
fViewer.setLabelProvider(new GitLabelProvider() {
@Override
public Image getImage(Object element) {
if (element instanceof GitModelCommitMockup)
return getChangesetIcon();
return super.getImage(element);
}
public String getText(Object element) {
if (element instanceof GitModelCommitMockup) {
String format = store.getString(UIPreferences.SYNC_VIEW_CHANGESET_LABEL_FORMAT);
String dateFormat = store.getString(UIPreferences.DATE_FORMAT);
return ((GitModelCommitMockup)element).getMokeupText(format, dateFormat);
}
return super.getText(element);
}
});
fViewer.setContentProvider(this);
fViewer.setInput(new GitModelCommitMockup());
}
public Object[] getChildren(Object parentElement) {
return new Object[0];
}
public Object getParent(Object element) {
return null;
}
public boolean hasChildren(Object element) {
return false;
}
public Object[] getElements(Object inputElement) {
return new Object[] { inputElement };
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// No-op
}
public void refresh() {
store = new PreferenceStore();
performOk(store);
fViewer.refresh(true);
}
}
/**
* NavigatorPreview control for showing how changes in the dialog will affect
* decoration
*/
private class NavigatorPreview extends Preview
implements ITreeContentProvider {
private DecorationHelper fHelper;
public NavigatorPreview(Composite composite) {
super(composite);
// Has to happen before the tree control is constructed
reloadDecorationHelper();
fViewer.setContentProvider(this);
fViewer.setLabelProvider(new ResLabelProvider());
fViewer.setInput(PREVIEW_FILESYSTEM_ROOT);
fViewer.expandAll();
fHelper = new DecorationHelper(new PreferenceStore());
}
private void reloadDecorationHelper() {
store = new PreferenceStore();
if (tabsInitialized)
performOk(store);
fHelper = new DecorationHelper(store);
}
public void refresh() {
reloadDecorationHelper();
fViewer.refresh(true);
setColorsAndFonts(fViewer.getTree().getItems());
}
private void setColorsAndFonts(TreeItem[] items) {
for (int i = 0; i < items.length; i++) {
DecorationResult decoration = getDecoration(items[i].getData());
items[i].setBackground(decoration.getBackgroundColor());
items[i].setForeground(decoration.getForegroundColor());
items[i].setFont(decoration.getFont());
setColorsAndFonts(items[i].getItems());
}
}
public Object[] getChildren(Object parentElement) {
return ((PreviewResource) parentElement).children.toArray();
}
public Object getParent(Object element) {
return null;
}
public boolean hasChildren(Object element) {
return !((PreviewResource) element).children.isEmpty();
}
public Object[] getElements(Object inputElement) {
return ((Collection) inputElement).toArray();
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// No-op
}
private DecorationResult getDecoration(Object element) {
DecorationResult decoration = new DecorationResult();
fHelper.decorate(decoration, (PreviewResource) element);
return decoration;
}
private class ResLabelProvider extends LabelProvider {
public String getText(Object element) {
final DecorationResult decoration = getDecoration(element);
final StringBuilder buffer = new StringBuilder();
final String prefix = decoration.getPrefix();
if (prefix != null)
buffer.append(prefix);
buffer.append(((PreviewResource) element).getName());
final String suffix = decoration.getSuffix();
if (suffix != null)
buffer.append(suffix);
return buffer.toString();
}
public Image getImage(Object element) {
final String s;
switch (((PreviewResource) element).type) {
case IResource.PROJECT:
s = SharedImages.IMG_OBJ_PROJECT;
break;
case IResource.FOLDER:
s = ISharedImages.IMG_OBJ_FOLDER;
break;
default:
s = ISharedImages.IMG_OBJ_FILE;
break;
}
final Image baseImage = PlatformUI.getWorkbench().getSharedImages()
.getImage(s);
final ImageDescriptor overlay = getDecoration(element).getOverlay();
if (overlay == null)
return baseImage;
try {
return fImageCache.createImage(new DecorationOverlayIcon(
baseImage, overlay, IDecoration.BOTTOM_RIGHT));
} catch (Exception e) {
Activator.logError(e.getMessage(), e);
}
return null;
}
}
}
private static class GitModelCommitMockup {
private static final String message = "Commit message text"; //$NON-NLS-1$
private static final String author = "Author Name"; //$NON-NLS-1$
private static final Date date = new Date();
private static final String committer = "Committer Name"; //$NON-NLS-1$
public String getMokeupText(String format, String dateFormat) {
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
Map<String, String> bindings = new HashMap<String, String>();
bindings.put(GitChangeSetLabelProvider.BINDING_CHANGESET_DATE, sdf.format(date));
bindings.put(GitChangeSetLabelProvider.BINDING_CHANGESET_AUTHOR, author);
bindings.put(GitChangeSetLabelProvider.BINDING_CHANGESET_COMMITTER, committer);
bindings.put(GitChangeSetLabelProvider.BINDING_CHANGESET_SHORT_MESSAGE, message);
return GitChangeSetLabelProvider.formatName(format, bindings);
}
}
private static class PreviewResource implements IDecoratableResource {
private final String name;
private final String repositoryName;
private final String branch;
private final String branchStatus;
private final int type;
private Collection children;
private boolean tracked;
private boolean ignored;
private boolean dirty;
private boolean conflicts;
private Staged staged;
private boolean assumeValid;
public PreviewResource(String name, int type, String repositoryName, String branch,
String branchStatus, boolean tracked, boolean ignored, boolean dirty, Staged staged,
boolean conflicts, boolean assumeValid) {
this.name = name;
this.repositoryName = repositoryName;
this.branch = branch;
this.branchStatus = branchStatus;
this.type = type;
this.children = Collections.EMPTY_LIST;
this.tracked = tracked;
this.ignored = ignored;
this.dirty = dirty;
this.staged = staged;
this.conflicts = conflicts;
this.assumeValid = assumeValid;
}
public String getName() {
return name;
}
public String getRepositoryName() {
return repositoryName;
}
public int getType() {
return type;
}
public String getBranch() {
return branch;
}
public String getBranchStatus() {
return branchStatus;
}
public boolean isTracked() {
return tracked;
}
public boolean isIgnored() {
return ignored;
}
public boolean isDirty() {
return dirty;
}
public Staged staged() {
return staged;
}
public boolean hasConflicts() {
return conflicts;
}
public boolean isAssumeValid() {
return assumeValid;
}
}
}