Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: d9804ad022878e2a00b00891f4ef067d2f48ece8 (plain) (tree)
1
2
3
4
5
6
7





                                                                                
                                                          














                                                                                 
                                                                       
                                                              
                                                            
                                                                       

















































                                                                             

                                                                

                                                                    
 

                                                                     
 

                                                          
 











                                                                         






                                                                                  
                                   
 







                                                                      








                                                                                       

                                                               

                                                              
                                        









                                                                                  








                                                                                       

                                                               
                                                                                

                                       
                                         

                                                                         
                                                     
                                                                     
                                           
                                        





































                                                                                 





                                                                                         
                                                           



















                                                                                                                 

                                                 




                                                                                                
                                                          






















                                                                                  





                                                                                       
                                                                                     
                                                          
                                                 
                                                           
                                                  
                                                
                                        
                                                      
                                              



                                           














                                                                                                      






































































                                                                                               

                                                                                          
                                                                  



                            















                                                                                     













                                                           
/*******************************************************************************
 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
 * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
 * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
 * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
 *
 * 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.dialogs;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.repository.RepositoriesViewContentProvider;
import org.eclipse.egit.ui.internal.repository.RepositoriesViewLabelProvider;
import org.eclipse.egit.ui.internal.repository.tree.AdditionalRefsNode;
import org.eclipse.egit.ui.internal.repository.tree.LocalNode;
import org.eclipse.egit.ui.internal.repository.tree.RefNode;
import org.eclipse.egit.ui.internal.repository.tree.RemoteTrackingNode;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeType;
import org.eclipse.egit.ui.internal.repository.tree.TagNode;
import org.eclipse.egit.ui.internal.repository.tree.TagsNode;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;

/**
 * The abstract base class to display a branch/tag selection dialog.
 * <p>
 * This will construct a tree similar to the Git Repositories View from which
 * the user can select an item. Concrete subclasses are responsible to check
 * whether the selection is valid and may add extra UI elements by overriding
 * {@link #createCustomArea(Composite)}.
 */
public abstract class AbstractBranchSelectionDialog extends TitleAreaDialog {

	/** The {@link Repository} used in the constructor */
	protected final Repository repo;

	/** The tree */
	protected TreeViewer branchTree;

	private String selectedBranch;

	private final String refToMark;

	private final RepositoryTreeNode<Repository> localBranches;

	private final RepositoryTreeNode<Repository> remoteBranches;

	private final RepositoryTreeNode<Repository> tags;

	private final RepositoryTreeNode<Repository> references;

	/** Determinate does local branches should be show or not */
	protected static final int SHOW_LOCAL_BRANCHES = 1 << 1;

	/** Determinate does remote branches should be show or not */
	protected static final int SHOW_REMOTE_BRANCHES = 1 << 2;

	/** Determinate does tags should be show or not */
	protected static final int SHOW_TAGS = 1 << 3;

	/** Determinate does references shout be show or not */
	protected static final int SHOW_REFERENCES = 1 << 4;

	/** Determinate does current should be selected or not */
	protected static final int SELECT_CURRENT_REF = 1 << 5;

	/** Determinate does local branches should be expanded or not */
	protected static final int EXPAND_LOCAL_BRANCHES_NODE = 1 << 6;

	/** Determinate does remote branches should be expanded or not */
	protected static final int EXPAND_REMOTE_BRANCHES_NODE = 1 << 7;

	/**
	 * Will allow select multiple branches. The implementer must override
	 * {@link AbstractBranchSelectionDialog#refNameFromDialog()} to be able to
	 * obtain list of selected branches
	 */
	protected static final int ALLOW_MULTISELECTION = 1 << 8;

	private final int settings;

	/**
	 * Construct a dialog to select a branch.
	 * <p>
	 * The currently checked out {@link Ref} is marked if possible
	 *
	 * @param parentShell
	 * @param repository
	 *            the {@link Repository}
	 * @param settings
	 *            configuration options of this dialog like
	 *            {@link AbstractBranchSelectionDialog#SHOW_LOCAL_BRANCHES},
	 *            {@link AbstractBranchSelectionDialog#SHOW_REMOTE_BRANCHES},
	 *            {@link AbstractBranchSelectionDialog#SHOW_TAGS},
	 *            {@link AbstractBranchSelectionDialog#SHOW_REFERENCES},
	 *            {@link AbstractBranchSelectionDialog#SELECT_CURRENT_REF},
	 *            {@link AbstractBranchSelectionDialog#EXPAND_LOCAL_BRANCHES_NODE},
	 *            {@link AbstractBranchSelectionDialog#EXPAND_REMOTE_BRANCHES_NODE}
	 */
	public AbstractBranchSelectionDialog(Shell parentShell,
			Repository repository, int settings) {
		this(parentShell, repository, null, settings);
		setHelpAvailable(false);
	}

	/**
	 * Construct a dialog to select a branch and specify a {@link Ref} to mark
	 *
	 * @param parentShell
	 * @param repository
	 *            the {@link Repository}
	 * @param refToMark
	 *            the name of the {@link Ref} to mark initially
	 * @param settings
	 *            configuration options of this dialog like
	 *            {@link AbstractBranchSelectionDialog#SHOW_LOCAL_BRANCHES},
	 *            {@link AbstractBranchSelectionDialog#SHOW_REMOTE_BRANCHES},
	 *            {@link AbstractBranchSelectionDialog#SHOW_TAGS},
	 *            {@link AbstractBranchSelectionDialog#SHOW_REFERENCES},
	 *            {@link AbstractBranchSelectionDialog#SELECT_CURRENT_REF},
	 *            {@link AbstractBranchSelectionDialog#EXPAND_LOCAL_BRANCHES_NODE},
	 *            {@link AbstractBranchSelectionDialog#EXPAND_REMOTE_BRANCHES_NODE}
	 */
	public AbstractBranchSelectionDialog(Shell parentShell,
			Repository repository, String refToMark, int settings) {
		super(parentShell);
		this.repo = repository;
		this.settings = settings;
		localBranches = new LocalNode(null, this.repo);
		remoteBranches = new RemoteTrackingNode(null, this.repo);
		tags = new TagsNode(null, this.repo);
		references = new AdditionalRefsNode(null, this.repo);
		this.refToMark = refToMark;
		setHelpAvailable(false);
	}

	/**
	 * Concrete subclasses should implement their check logic around this
	 *
	 * @param refName
	 *            the name of the currently selected {@link Ref}, may be null
	 */
	protected abstract void refNameSelected(String refName);

	/**
	 * Subclasses must provide the title of the dialog
	 *
	 * @return the title of the dialog
	 */
	protected abstract String getTitle();

	/**
	 * @return the message shown above the refs tree
	 */
	protected abstract String getMessageText();

	/**
	 * Subclasses should provide the title of the dialog window
	 * <p>
	 * Defaults to {@link #getTitle()}
	 *
	 * @return the title of the dialog window
	 */
	protected String getWindowTitle() {
		return getTitle();
	}

	@Override
	protected final Composite createDialogArea(Composite base) {
		Composite parent = (Composite) super.createDialogArea(base);
		parent.setLayout(GridLayoutFactory.fillDefaults().create());

		int selectionModel = -1;
		if ((settings & ALLOW_MULTISELECTION) != 0)
			selectionModel = SWT.MULTI;
		else
			selectionModel = SWT.SINGLE;
		FilteredTree tree = new FilteredTree(parent, selectionModel | SWT.BORDER,
				new PatternFilter(), true);
		branchTree = tree.getViewer();
		branchTree.setLabelProvider(new RepositoriesViewLabelProvider());
		branchTree.setContentProvider(new RepositoriesViewContentProvider());

		GridDataFactory.fillDefaults().grab(true, true).hint(500, 300).applyTo(
				tree);
		branchTree.addSelectionChangedListener(new ISelectionChangedListener() {

			public void selectionChanged(SelectionChangedEvent event) {
				String refName = refNameFromDialog();
				refNameSelected(refName);
			}
		});

		// double-click support
		branchTree.addOpenListener(new IOpenListener() {

			public void open(OpenEvent event) {
				RepositoryTreeNode node = (RepositoryTreeNode) ((IStructuredSelection) branchTree
						.getSelection()).getFirstElement();
				if (node == null)
					return;
				if (node.getType() != RepositoryTreeNodeType.REF
						&& node.getType() != RepositoryTreeNodeType.TAG)
					branchTree.setExpandedState(node, !branchTree
							.getExpandedState(node));
				else if (getButton(Window.OK).isEnabled())
					buttonPressed(OK);

			}
		});

		createCustomArea(parent);

		setTitle(getTitle());
		setMessage(getMessageText());
		getShell().setText(getWindowTitle());

		applyDialogFont(parent);

		return parent;
	}

	/**
	 * Concrete subclasses must issue a call to super.create() when overriding
	 * this
	 */
	@Override
	public void create() {
		super.create();

		// Initially disable OK button, as the required user inputs may not be
		// complete after the dialog is first shown. If automatic selections
		// happen after this (making the user inputs complete), the button will
		// be enabled.
		getButton(Window.OK).setEnabled(false);

		List<RepositoryTreeNode> roots = new ArrayList<RepositoryTreeNode>();
		if ((settings & SHOW_LOCAL_BRANCHES) != 0)
			roots.add(localBranches);
		if ((settings & SHOW_REMOTE_BRANCHES) != 0)
			roots.add(remoteBranches);
		if ((settings & SHOW_TAGS) != 0)
			roots.add(tags);
		if ((settings & SHOW_REFERENCES) != 0)
			roots.add(references);

		branchTree.setInput(roots);

		try {
			if ((settings & SELECT_CURRENT_REF) != 0)
				if (refToMark != null)
					markRef(refToMark);
				else {
					// initially, we mark the current head if it can be determined
					String fullBranch = repo.getFullBranch();
					markRef(fullBranch);
				}
			if ((settings & EXPAND_LOCAL_BRANCHES_NODE) != 0)
				// if we can't determine a branch, we just expand local
				// branches
				branchTree.expandToLevel(localBranches, 1);
			if ((settings & EXPAND_REMOTE_BRANCHES_NODE) != 0)
				// minor UX improvement to always expand remote branches node
				branchTree.expandToLevel(remoteBranches, 1);
		} catch (IOException e) {
			// ignore
		}
	}

	/**
	 * Set the selection to a {@link Ref} if possible
	 *
	 * @param refName
	 *            the name of the {@link Ref}
	 * @return <code>true</code> if the {@link Ref} with the given name was
	 *         found
	 */
	protected boolean markRef(String refName) {
		// selects the entry specified by the name
		if (refName == null)
			return false;

		RepositoryTreeNode node;
		try {
			if (refName.startsWith(Constants.R_HEADS)) {
				Ref ref = this.repo.getRef(refName);
				node = new RefNode(localBranches, this.repo, ref);
			} else {
				String mappedRef = Activator.getDefault().getRepositoryUtil()
						.mapCommitToRef(this.repo, refName, false);
				if (mappedRef != null
						&& mappedRef.startsWith(Constants.R_REMOTES)) {
					Ref ref = this.repo.getRef(mappedRef);
					node = new RefNode(remoteBranches, this.repo, ref);
				} else if (mappedRef != null
						&& mappedRef.startsWith(Constants.R_TAGS)) {
					Ref ref = this.repo.getRef(mappedRef);
					node = new TagNode(tags, this.repo, ref);
				} else {
					return false;
				}
			}
		} catch (IOException e) {
			return false;
		}

		branchTree.setSelection(new StructuredSelection(node), true);
		return true;
	}

	/**
	 * Will only work after the dialog was closed with the OK button
	 *
	 * @return the selected refName
	 */
	public String getRefName() {
		return this.selectedBranch;
	}

	@Override
	protected void okPressed() {
		this.selectedBranch = refNameFromDialog();
		super.okPressed();
	}

	/**
	 * @return the selected ref name from the tree, may be null
	 */
	protected String refNameFromDialog() {
		IStructuredSelection sel = (IStructuredSelection) branchTree
				.getSelection();
		if (sel.size() != 1)
			return null;
		RepositoryTreeNode node = (RepositoryTreeNode) sel.getFirstElement();
		if (node.getType() == RepositoryTreeNodeType.REF
				|| node.getType() == RepositoryTreeNodeType.TAG
				|| node.getType() == RepositoryTreeNodeType.ADDITIONALREF)
			return ((Ref) node.getObject()).getName();
		return null;
	}

	/**
	 * @return the selected {@link Ref} from the tree, may be null
	 */
	protected Ref refFromDialog() {
		IStructuredSelection sel = (IStructuredSelection) branchTree
				.getSelection();
		if (sel.size() != 1)
			return null;
		RepositoryTreeNode node = (RepositoryTreeNode) sel.getFirstElement();
		if (node.getType() == RepositoryTreeNodeType.REF
				|| node.getType() == RepositoryTreeNodeType.TAG) {
			return ((Ref) node.getObject());
		}
		return null;
	}

	/**
	 * Subclasses may add UI elements
	 *
	 * @param parent
	 */
	protected void createCustomArea(Composite parent) {
		// do nothing
	}

	@Override
	protected int getShellStyle() {
		return super.getShellStyle() | SWT.RESIZE;
	}

}

Back to the top