/******************************************************************************* * Copyright (c) 2010 IBM Corporation 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: * IBM Corporation - initial API and implementation * Dariusz Luksza <dariusz@luksza.org> *******************************************************************************/ package org.eclipse.egit.ui.internal.synchronize; 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.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.egit.core.project.RepositoryMapping; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.internal.CommonUtils; import org.eclipse.egit.ui.internal.UIIcons; import org.eclipse.egit.ui.internal.UIText; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.preference.JFacePreferences; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ComboBoxCellEditor; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.StyledCellLabelProvider; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; 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; class GitSynchronizeWizardPage extends WizardPage { private static final IWorkspaceRoot ROOT = ResourcesPlugin.getWorkspace() .getRoot(); private boolean forceFetch; private boolean shouldIncludeLocal = false; private TreeViewer treeViewer; private final Map<Repository, Set<IProject>> resources = new HashMap<>(); private final Map<Repository, String> selectedBranches = new HashMap<>(); private final Image branchImage = UIIcons.BRANCH.createImage(); private final Image repositoryImage = UIIcons.REPOSITORY.createImage(); GitSynchronizeWizardPage() { super(GitSynchronizeWizardPage.class.getName()); setTitle(UIText.GitBranchSynchronizeWizardPage_title); setMessage(UIText.GitBranchSynchronizeWizardPage_description, WARNING); } @Override public void createControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(1, false); layout.marginWidth = 0; layout.marginHeight = 0; composite.setLayout(layout); for (IProject project : ROOT.getProjects()) { RepositoryMapping repositoryMapping = RepositoryMapping .getMapping(project); if (repositoryMapping == null) continue; Repository repo = repositoryMapping.getRepository(); Set<IProject> projects = resources.get(repo); if (projects == null) { projects = new HashSet<>(); resources.put(repo, projects); } projects.add(project); } treeViewer = new TreeViewer(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION); treeViewer.getTree().setLinesVisible(true); treeViewer.getTree().setHeaderVisible(true); treeViewer.getTree().setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true)); TreeViewerColumn projectsColumn = new TreeViewerColumn(treeViewer, SWT.LEAD); projectsColumn.getColumn().setText( UIText.GitBranchSynchronizeWizardPage_repository); projectsColumn.getColumn().setImage(repositoryImage); projectsColumn.setLabelProvider(new StyledCellLabelProvider() { @Override public void update(ViewerCell cell) { Object element = cell.getElement(); if (element instanceof Repository) { Repository repo = (Repository) element; String descr = ""; //$NON-NLS-1$ try { descr += " [" + repo.getBranch() + "]";//$NON-NLS-1$ //$NON-NLS-2$ } catch (IOException e) { Activator.logError(e.getMessage(), e); } Color decorationsColor = JFaceResources.getColorRegistry() .get(JFacePreferences.DECORATIONS_COLOR); String repoName = repo.getWorkTree().getName(); int repoNameLen = repoName.length(); StyleRange styleRange = new StyleRange(repoNameLen, repoNameLen + descr.length(), decorationsColor, null); cell.setImage(repositoryImage); cell.setText(repoName + descr); cell.setStyleRanges(new StyleRange[] { styleRange }); } super.update(cell); } }); TreeViewerColumn dstColumn = new TreeViewerColumn(treeViewer, SWT.LEAD); dstColumn.getColumn().setText( UIText.GitBranchSynchronizeWizardPage_destination); dstColumn.getColumn().setImage(branchImage); dstColumn.getColumn().setWidth(200); final ComboBoxCellEditor branchesEditor = new ComboBoxCellEditor( treeViewer.getTree(), new String[0]); branchesEditor .setActivationStyle(ComboBoxCellEditor.DROP_DOWN_ON_KEY_ACTIVATION | ComboBoxCellEditor.DROP_DOWN_ON_MOUSE_ACTIVATION); ((CCombo) branchesEditor.getControl()).addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { CCombo combo = (CCombo) e.widget; TreeSelection sel = (TreeSelection) treeViewer.getSelection(); int selectedIdx = combo.getSelectionIndex(); Repository repo = (Repository) sel.getFirstElement(); if (selectedIdx != -1) { selectedBranches.put(repo, combo.getItem(selectedIdx)); setPageComplete(true); } else { selectedBranches.put(repo, null); setPageComplete(false); } } }); dstColumn.setEditingSupport(new EditingSupport(treeViewer) { @Override protected void setValue(Object element, Object value) { int intValue = ((Integer) value).intValue(); if (intValue == -1) return; CCombo combo = (CCombo) branchesEditor.getControl(); String branch = combo.getItem(intValue); selectedBranches.put((Repository) element, branch); treeViewer.refresh(element, true); validatePage(); } @Override protected Object getValue(Object element) { String branch = selectedBranches.get(element); CCombo combo = (CCombo) branchesEditor.getControl(); int index = branch == null ? 0 : combo.indexOf(branch); return Integer.valueOf(index); } @Override protected CellEditor getCellEditor(Object element) { Repository repo = (Repository) element; List<String> refs = new LinkedList<>(repo.getAllRefs() .keySet()); List<Ref> additionalRefs; try { additionalRefs = repo.getRefDatabase().getAdditionalRefs(); } catch (IOException e) { additionalRefs = null; } if (additionalRefs != null) for (Ref ref : additionalRefs) refs.add(ref.getName()); Collections.sort(refs, CommonUtils.STRING_ASCENDING_COMPARATOR); branchesEditor.setItems(refs.toArray(new String[refs.size()])); return branchesEditor; } @Override protected boolean canEdit(Object element) { return true; } }); dstColumn.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { String branch = selectedBranches.get(element); return branch == null ? "" : branch; //$NON-NLS-1$ } }); treeViewer.setContentProvider(new ITreeContentProvider() { @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // nothing to do } @Override public void dispose() { // nothing to do } @Override public Object[] getElements(Object inputElement) { return (Object[]) inputElement; } @Override public boolean hasChildren(Object element) { return false; } @Override public Object getParent(Object element) { return null; } @Override public Object[] getChildren(Object parentElement) { return new Object[0]; } }); List<Repository> repositoriesList = new ArrayList<>( resources.keySet()); Collections.sort(repositoriesList, new Comparator<Repository>() { @Override public int compare(Repository o1, Repository o2) { String name1 = o1.getWorkTree().getName(); String name2 = o2.getWorkTree().getName(); return name1.compareToIgnoreCase(name2); } }); treeViewer.setInput(repositoriesList .toArray(new Repository[repositoriesList.size()])); projectsColumn.getColumn().pack(); Composite buttonsComposite = new Composite(composite, SWT.NONE); layout = new GridLayout(4, false); layout.numColumns = 1; layout.marginWidth = 0; layout.marginHeight = 0; buttonsComposite.setLayout(layout); buttonsComposite.setLayoutData(GridDataFactory.fillDefaults() .grab(true, false).create()); final Button fetchChanges = new Button(buttonsComposite, SWT.CHECK); fetchChanges .setText(UIText.GitBranchSynchronizeWizardPage_fetchChangesFromRemote); fetchChanges.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { forceFetch = fetchChanges.getSelection(); } }); fetchChanges.setLayoutData(GridDataFactory.fillDefaults() .grab(true, false).create()); fetchChanges.setSelection(Activator.getDefault().getPreferenceStore() .getBoolean(UIPreferences.SYNC_VIEW_FETCH_BEFORE_LAUNCH)); final Button includeLocal = new Button(buttonsComposite, SWT.CHECK); includeLocal .setText(UIText.GitBranchSynchronizeWizardPage_includeUncommitedChanges); includeLocal.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { shouldIncludeLocal = includeLocal.getSelection(); } }); includeLocal.setLayoutData(GridDataFactory.fillDefaults() .grab(true, false).create()); Dialog.applyDialogFont(composite); setPageComplete(false); setControl(composite); } @Override public void dispose() { if (branchImage != null) branchImage.dispose(); if (repositoryImage != null) repositoryImage.dispose(); super.dispose(); } private void validatePage() { setPageComplete(!selectedBranches.isEmpty()); } Map<Repository, String> getSelectedBranches() { return selectedBranches; } Set<IProject> getSelectedProjects() { Set<IProject> projects = new HashSet<>(); for (Repository repo : selectedBranches.keySet()) projects.addAll(resources.get(repo)); return projects; } boolean shouldIncludeLocal() { return shouldIncludeLocal; } boolean forceFetch() { return forceFetch; } }