/******************************************************************************* * Copyright (c) 2010, SAP AG. * 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: * Mathias Kinzler (SAP AG) - initial implementation *******************************************************************************/ package org.eclipse.egit.ui.internal.preferences; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.egit.core.RepositoryCache; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.internal.SWTUtils; import org.eclipse.egit.ui.internal.UIText; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jgit.events.ConfigChangedEvent; import org.eclipse.jgit.events.ConfigChangedListener; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.SystemReader; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Combo; 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.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; /** * Displays the global Git configuration and allows to edit it. * <p> * In EGit, this maps to the user configuration. */ public class GlobalConfigurationPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { /** The ID of this page */ public static final String ID = "org.eclipse.egit.ui.internal.preferences.GlobalConfigurationPreferencePage"; //$NON-NLS-1$ private FileBasedConfig userConfig; private FileBasedConfig sysConfig; private StackLayout repoConfigStackLayout; private List<Repository> repositories; private Map<Repository, ConfigurationEditorComponent> repoConfigEditors = new HashMap<>(); private Set<Repository> dirtyRepositories = new HashSet<>(); private boolean userIsDirty; private boolean sysIsDirty; private ConfigurationEditorComponent userConfigEditor; private ConfigurationEditorComponent sysConfigEditor; private Composite repoConfigComposite; @Override protected Control createContents(Composite parent) { Composite composite = SWTUtils.createHVFillComposite(parent, SWTUtils.MARGINS_NONE); TabFolder tabFolder = new TabFolder(composite, SWT.NONE); tabFolder.setLayoutData(SWTUtils.createHVFillGridData()); userConfigEditor = new ConfigurationEditorComponent(tabFolder, userConfig, true) { @Override protected void setErrorMessage(String message) { GlobalConfigurationPreferencePage.this.setErrorMessage(message); } @Override protected void setDirty(boolean dirty) { userIsDirty = dirty; updateApplyButton(); } }; sysConfigEditor = new ConfigurationEditorComponent(tabFolder, sysConfig, true) { @Override protected void setErrorMessage(String message) { GlobalConfigurationPreferencePage.this.setErrorMessage(message); } @Override protected void setDirty(boolean dirty) { sysIsDirty = dirty; updateApplyButton(); } }; Control result = userConfigEditor.createContents(); Dialog.applyDialogFont(result); TabItem userTabItem = new TabItem(tabFolder, SWT.FILL); userTabItem.setControl(result); userTabItem.setText(UIText.GlobalConfigurationPreferencePage_userSettingTabTitle); result = sysConfigEditor.createContents(); Dialog.applyDialogFont(result); TabItem sysTabItem = new TabItem(tabFolder, SWT.FILL); sysTabItem.setControl(result); sysTabItem.setText(UIText.GlobalConfigurationPreferencePage_systemSettingTabTitle); Composite repoTab = new Composite(tabFolder, SWT.NONE); GridLayoutFactory.swtDefaults().margins(0, 0).applyTo(repoTab); GridDataFactory.fillDefaults().grab(true, true).applyTo(repoTab); Composite repositoryComposite = new Composite(repoTab, SWT.NONE); repositoryComposite.setLayout(new GridLayout(2, false)); GridDataFactory.fillDefaults().grab(true, false).applyTo( repositoryComposite); Label repoLabel = new Label(repositoryComposite, SWT.NONE); repoLabel .setText(UIText.GlobalConfigurationPreferencePage_repositorySettingRepositoryLabel); Combo repoCombo = new Combo(repositoryComposite, SWT.READ_ONLY); repoCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Combo combo = (Combo) e.widget; showRepositoryConfiguration(combo.getSelectionIndex()); } }); repoCombo.setItems(getRepositoryComboItems()); repoConfigComposite = new Composite(repoTab, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(repoConfigComposite); repoConfigStackLayout = new StackLayout(); repoConfigComposite.setLayout(repoConfigStackLayout); TabItem repoTabItem = new TabItem(tabFolder, SWT.FILL); repoTabItem.setControl(repoTab); repoTabItem.setText(UIText.GlobalConfigurationPreferencePage_repositorySettingTabTitle); if (repoCombo.getItemCount() > 0) { repoCombo.select(0); showRepositoryConfiguration(0); } else { repoCombo.setItems(new String[] {UIText.GlobalConfigurationPreferencePage_repositorySettingNoRepositories}); repoCombo.select(0); repoCombo.setEnabled(false); } return composite; } @Override public void setVisible(boolean visible) { if (visible) updateApplyButton(); super.setVisible(visible); } @Override protected void updateApplyButton() { if (getApplyButton() != null) getApplyButton().setEnabled(userIsDirty || sysIsDirty || !dirtyRepositories.isEmpty()); } @Override public boolean performOk() { boolean ok = true; if (userIsDirty) { try { userConfigEditor.save(); } catch (IOException e) { Activator.handleError(e.getMessage(), e, true); ok = false; } } if (sysIsDirty) { try { sysConfigEditor.save(); } catch (IOException e) { Activator.handleError(e.getMessage(), e, true); ok = false; } } // Use array since calling save updates the dirty state which updates // the set of dirty repositories that is being iterated over final Repository[] repos = dirtyRepositories .toArray(new Repository[dirtyRepositories.size()]); for (Repository repository : repos) { ConfigurationEditorComponent editor = repoConfigEditors.get(repository); try { editor.save(); } catch (IOException e) { Activator.handleError(e.getMessage(), e, true); ok = false; } } return ok; } @Override protected void performDefaults() { try { userConfigEditor.restore(); sysConfigEditor.restore(); for (ConfigurationEditorComponent editor : repoConfigEditors.values()) { editor.restore(); } } catch (IOException e) { Activator.handleError(e.getMessage(), e, true); } super.performDefaults(); } @Override public void init(IWorkbench workbench) { if (sysConfig == null) sysConfig = SystemReader.getInstance().openSystemConfig(null, FS.DETECTED); if (userConfig == null) userConfig = SystemReader.getInstance().openUserConfig(null, FS.DETECTED); // no inherit here! if (repositories == null) { repositories = new ArrayList<>(); List<String> repoPaths = Activator.getDefault().getRepositoryUtil().getConfiguredRepositories(); RepositoryCache repositoryCache = org.eclipse.egit.core.Activator.getDefault().getRepositoryCache(); for (String repoPath : repoPaths) { File gitDir = new File(repoPath); if (!gitDir.exists()) continue; try { repositories.add(repositoryCache.lookupRepository(gitDir)); } catch (IOException e) { continue; } } sortRepositoriesByName(); } } private String getName(final Repository repo) { return Activator.getDefault().getRepositoryUtil() .getRepositoryName(repo); } private void sortRepositoriesByName() { Collections.sort(repositories, new Comparator<Repository>() { @Override public int compare(Repository repo1, Repository repo2) { return getName(repo1).compareTo(getName(repo2)); } }); } private String[] getRepositoryComboItems() { List<String> items = new ArrayList<>(); for (Repository repository : repositories) { String repoName = getName(repository); if (repoName.length() > 0) items.add(repoName); } return items.toArray(new String[items.size()]); } private void showRepositoryConfiguration(int index) { Repository repository = repositories.get(index); ConfigurationEditorComponent editor = repoConfigEditors.get(repository); if (editor == null) { editor = createConfigurationEditor(repository); repoConfigEditors.put(repository, editor); } repoConfigStackLayout.topControl = editor.getContents(); repoConfigComposite.layout(); } private ConfigurationEditorComponent createConfigurationEditor(final Repository repository) { StoredConfig repositoryConfig; if (repository.getConfig() instanceof FileBasedConfig) { File configFile = ((FileBasedConfig) repository.getConfig()).getFile(); repositoryConfig = new FileBasedConfig(configFile, repository .getFS()); repositoryConfig.addChangeListener(new ConfigChangedListener() { @Override public void onConfigChanged(ConfigChangedEvent event) { repository.getListenerList().dispatch( new ConfigChangedEvent()); } }); } else { repositoryConfig = repository.getConfig(); } ConfigurationEditorComponent editorComponent = new ConfigurationEditorComponent( repoConfigComposite, repositoryConfig, true) { @Override protected void setErrorMessage(String message) { GlobalConfigurationPreferencePage.this.setErrorMessage(message); } @Override protected void setDirty(boolean dirty) { if (dirty) dirtyRepositories.add(repository); else dirtyRepositories.remove(repository); updateApplyButton(); } }; editorComponent.createContents(); return editorComponent; } }