From 2428b1cab84530e94196e1dfc51e38cb0a3e5ae8 Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Wed, 10 May 2017 15:36:27 +0200 Subject: [PATCH] Fix node selection in AbstractBranchSelectionDialog Depending on the mode of the content provider (hierarchical or not) we need to create nodes differently in order to successfully pre-select a tree item. Bug: 516411 Change-Id: I5319bb8fdeececb81a3aa51cf1b0faab454eabbf Signed-off-by: Thomas Wolf --- .../GitRepositoriesViewBranchHandlingTest.java | 46 ++++++++++++++++++++++ .../dialogs/AbstractBranchSelectionDialog.java | 42 ++++++++++++++++++-- .../RepositoriesViewContentProvider.java | 11 ++++++ 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewBranchHandlingTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewBranchHandlingTest.java index faedd7a78..a206aaed6 100644 --- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewBranchHandlingTest.java +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewBranchHandlingTest.java @@ -21,13 +21,16 @@ import java.text.MessageFormat; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import org.eclipse.core.commands.State; import org.eclipse.egit.core.RepositoryUtil; import org.eclipse.egit.core.op.BranchOperation; import org.eclipse.egit.core.op.CloneOperation; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.JobFamilies; +import org.eclipse.egit.ui.internal.CommonUtils; import org.eclipse.egit.ui.internal.UIText; import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator; +import org.eclipse.egit.ui.internal.repository.tree.command.ToggleBranchHierarchyCommand; import org.eclipse.egit.ui.test.ContextMenuHelper; import org.eclipse.egit.ui.test.TestUtil; import org.eclipse.jface.dialogs.IDialogConstants; @@ -44,7 +47,9 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.transport.URIish; import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; import org.eclipse.swtbot.swt.finder.waits.Conditions; import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; @@ -52,6 +57,8 @@ import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -361,6 +368,45 @@ public class GitRepositoriesViewBranchHandlingTest extends } @Test + public void testRebaseDialogOnRepo() throws Exception { + ICommandService srv = CommonUtils.getService(PlatformUI.getWorkbench(), + ICommandService.class); + State commandState = srv.getCommand(ToggleBranchHierarchyCommand.ID) + .getState(ToggleBranchHierarchyCommand.TOGGLE_STATE); + Boolean isHierarchical = (Boolean) commandState.getValue(); + commandState.setValue(Boolean.TRUE); + try { + SWTBotTree tree = getOrOpenView().bot().tree(); + + myRepoViewUtil.getRootItem(tree, clonedRepositoryFile).select(); + + ContextMenuHelper.clickContextMenu(tree, + myUtil.getPluginLocalizedValue("RebaseCommand.label2")); + + String title = MessageFormat.format( + UIText.RebaseTargetSelectionDialog_RebaseTitleWithBranch, + FileRepositoryBuilder.create(clonedRepositoryFile) + .getBranch()); + + SWTBotShell targetSelectionDialog = bot.shell(title); + SWTBot dialogBot = targetSelectionDialog.bot(); + SWTBotTree dialogTree = dialogBot.tree(); + assertEquals("Should have a node selected", 1, + dialogTree.selectionCount()); + String[] result = { null }; + PlatformUI.getWorkbench().getDisplay().syncExec(() -> { + TreeItem[] selected = dialogTree.widget.getSelection(); + result[0] = selected[0].getText(); + }); + assertTrue("master node should be selected", + result[0] != null && result[0].contains("master")); + targetSelectionDialog.close(); + } finally { + commandState.setValue(isHierarchical); + } + } + + @Test public void testBranchConfiguration() throws Exception { Repository repo = lookupRepository(clonedRepositoryFile); try (Git git = new Git(repo)) { diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java index 650c5a333..3b8c37d97 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java @@ -21,12 +21,14 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import org.eclipse.core.runtime.Path; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIUtils; import org.eclipse.egit.ui.internal.repository.RepositoriesViewContentProvider; import org.eclipse.egit.ui.internal.repository.RepositoriesViewStyledCellLabelProvider; import org.eclipse.egit.ui.internal.repository.tree.AdditionalRefNode; import org.eclipse.egit.ui.internal.repository.tree.AdditionalRefsNode; +import org.eclipse.egit.ui.internal.repository.tree.BranchHierarchyNode; 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; @@ -40,6 +42,7 @@ import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; @@ -269,6 +272,7 @@ public abstract class AbstractBranchSelectionDialog extends TitleAreaDialog { FilteredTree tree = new FilteredTree(composite, selectionModel | SWT.BORDER, new PatternFilter(), true); branchTree = tree.getViewer(); + branchTree.setUseHashlookup(true); branchTree .setLabelProvider(new RepositoriesViewStyledCellLabelProvider()); branchTree.setContentProvider(new RepositoriesViewContentProvider()); @@ -408,12 +412,12 @@ public abstract class AbstractBranchSelectionDialog extends TitleAreaDialog { Ref ref = repo.exactRef(refName); if (ref == null) return false; - node = new RefNode(localBranches, repo, ref); + node = createRefNode(localBranches, repo, ref); } else if (refName.startsWith(Constants.R_REMOTES)) { Ref ref = repo.exactRef(refName); if (ref == null) return false; - node = new RefNode(remoteBranches, repo, ref); + node = createRefNode(remoteBranches, repo, ref); } else if (Constants.HEAD.equals(refName)) { Ref ref = repo.exactRef(refName); if (ref == null) @@ -427,7 +431,7 @@ public abstract class AbstractBranchSelectionDialog extends TitleAreaDialog { Ref ref = repo.exactRef(mappedRef); if (ref == null) return false; - node = new RefNode(remoteBranches, repo, ref); + node = createRefNode(remoteBranches, repo, ref); } else if (mappedRef != null && mappedRef.startsWith(Constants.R_TAGS)) { Ref ref = repo.exactRef(mappedRef); @@ -440,11 +444,41 @@ public abstract class AbstractBranchSelectionDialog extends TitleAreaDialog { } catch (IOException e) { return false; } - branchTree.setSelection(new StructuredSelection(node), true); return true; } + private RefNode createRefNode(RepositoryTreeNode root, + Repository repository, Ref ref) { + IContentProvider cp = branchTree.getContentProvider(); + if (cp instanceof RepositoriesViewContentProvider + && ((RepositoriesViewContentProvider) cp).isHierarchical()) { + // Create intermediary BranchHierarchyNodes + String fullName = ref.getName(); + int i = 0; + if (fullName.startsWith(Constants.R_HEADS)) { + i = Constants.R_HEADS.length(); + } else if (fullName.startsWith(Constants.R_REMOTES)) { + i = Constants.R_REMOTES.length(); + } + RepositoryTreeNode top = root; + int l = fullName.length(); + while (i < l) { + int j = fullName.indexOf('/', i); + if (j > i) { + top = new BranchHierarchyNode(top, repository, + new Path(fullName.substring(0, j))); + i = j + 1; + } else { + break; + } + } + return new RefNode(top, repository, ref); + } else { + return new RefNode(root, repository, ref); + } + } + /** * Will only work after the dialog was closed with the OK button * diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesViewContentProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesViewContentProvider.java index 163d1151e..98a63b0cb 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesViewContentProvider.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesViewContentProvider.java @@ -650,4 +650,15 @@ public class RepositoriesViewContentProvider implements ITreeContentProvider, return false; } } + + /** + * Tells whether this content provider is using a hierarchical branch + * layout. + * + * @return {@code true} if this content provider uses a hierarchical branch + * layout; {@code false} otherwise + */ + public boolean isHierarchical() { + return branchHierarchyMode; + } } -- 2.11.4.GIT