Honor workbench setting for Dialog font
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / dialogs / BranchSelectionDialog.java
bloba30fb2a1194371010bf593a7494b77730421150a
1 /*******************************************************************************
2 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
3 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
4 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
5 * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
7 * All rights reserved. This program and the accompanying materials
8 * are made available under the terms of the Eclipse Public License v1.0
9 * which accompanies this distribution, and is available at
10 * http://www.eclipse.org/legal/epl-v10.html
11 *******************************************************************************/
12 package org.eclipse.egit.ui.internal.dialogs;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.List;
18 import org.eclipse.egit.ui.Activator;
19 import org.eclipse.egit.ui.UIText;
20 import org.eclipse.egit.ui.internal.ValidationUtils;
21 import org.eclipse.egit.ui.internal.repository.RepositoriesViewContentProvider;
22 import org.eclipse.egit.ui.internal.repository.RepositoriesViewLabelProvider;
23 import org.eclipse.egit.ui.internal.repository.tree.LocalBranchesNode;
24 import org.eclipse.egit.ui.internal.repository.tree.RefNode;
25 import org.eclipse.egit.ui.internal.repository.tree.RemoteBranchesNode;
26 import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
27 import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeType;
28 import org.eclipse.egit.ui.internal.repository.tree.TagNode;
29 import org.eclipse.egit.ui.internal.repository.tree.TagsNode;
30 import org.eclipse.jface.dialogs.IDialogConstants;
31 import org.eclipse.jface.dialogs.InputDialog;
32 import org.eclipse.jface.dialogs.TitleAreaDialog;
33 import org.eclipse.jface.layout.GridDataFactory;
34 import org.eclipse.jface.layout.GridLayoutFactory;
35 import org.eclipse.jface.resource.JFaceResources;
36 import org.eclipse.jface.viewers.IOpenListener;
37 import org.eclipse.jface.viewers.ISelectionChangedListener;
38 import org.eclipse.jface.viewers.IStructuredSelection;
39 import org.eclipse.jface.viewers.OpenEvent;
40 import org.eclipse.jface.viewers.SelectionChangedEvent;
41 import org.eclipse.jface.viewers.StructuredSelection;
42 import org.eclipse.jface.viewers.TreeViewer;
43 import org.eclipse.jface.window.Window;
44 import org.eclipse.jgit.lib.Constants;
45 import org.eclipse.jgit.lib.ObjectId;
46 import org.eclipse.jgit.lib.Ref;
47 import org.eclipse.jgit.lib.RefRename;
48 import org.eclipse.jgit.lib.RefUpdate;
49 import org.eclipse.jgit.lib.Repository;
50 import org.eclipse.jgit.lib.RefUpdate.Result;
51 import org.eclipse.osgi.util.NLS;
52 import org.eclipse.swt.SWT;
53 import org.eclipse.swt.events.SelectionAdapter;
54 import org.eclipse.swt.events.SelectionEvent;
55 import org.eclipse.swt.layout.GridLayout;
56 import org.eclipse.swt.widgets.Button;
57 import org.eclipse.swt.widgets.Composite;
58 import org.eclipse.swt.widgets.Shell;
59 import org.eclipse.ui.dialogs.FilteredTree;
60 import org.eclipse.ui.dialogs.PatternFilter;
62 /**
63 * The branch and reset selection dialog
65 public class BranchSelectionDialog extends TitleAreaDialog {
67 private final Repository repo;
69 private TreeViewer branchTree;
71 /**
72 * button which finally triggers the action
74 protected Button confirmationBtn;
76 private Button renameButton;
78 private Button newButton;
80 private String selectedBranch;
82 private final RepositoryTreeNode<Repository> localBranches;
84 private final RepositoryTreeNode<Repository> remoteBranches;
86 private final RepositoryTreeNode<Repository> tags;
88 /**
89 * Construct a dialog to select a branch to reset to or check out
90 * @param parentShell
91 * @param repo
93 public BranchSelectionDialog(Shell parentShell, Repository repo) {
94 super(parentShell);
95 this.repo = repo;
96 localBranches = new LocalBranchesNode(null, this.repo);
97 remoteBranches = new RemoteBranchesNode(null, this.repo);
98 tags = new TagsNode(null, this.repo);
101 @Override
102 protected Composite createDialogArea(Composite base) {
103 Composite parent = (Composite) super.createDialogArea(base);
104 parent.setLayout(GridLayoutFactory.fillDefaults().create());
106 // TODO deprecated constructor for now
107 FilteredTree tree = new FilteredTree(parent, SWT.SINGLE | SWT.BORDER, new PatternFilter());
108 branchTree = tree.getViewer();
109 new RepositoriesViewLabelProvider(branchTree);
110 branchTree.setContentProvider(new RepositoriesViewContentProvider());
112 GridDataFactory.fillDefaults().grab(true, true).hint(500, 300).applyTo(
113 tree);
114 branchTree.addSelectionChangedListener(new ISelectionChangedListener() {
116 public void selectionChanged(SelectionChangedEvent event) {
117 // enable the buttons depending on the selection
119 String refName = refNameFromDialog();
121 boolean tagSelected = refName != null
122 && refName.startsWith(Constants.R_TAGS);
124 boolean branchSelected = refName != null
125 && (refName.startsWith(Constants.R_HEADS) || refName
126 .startsWith(Constants.R_REMOTES));
128 // we don't allow reset on tags, but checkout
129 if (!canConfirmOnTag())
130 confirmationBtn.setEnabled(branchSelected);
131 else
132 confirmationBtn.setEnabled(branchSelected || tagSelected);
134 // we don't support rename on tags
135 if (renameButton != null) {
136 renameButton.setEnabled(branchSelected && !tagSelected
137 && !tagSelected);
140 // new branch can not be based on a tag
141 if (newButton != null) {
142 newButton.setEnabled(branchSelected && !tagSelected);
147 // double-click support
148 branchTree.addOpenListener(new IOpenListener() {
150 public void open(OpenEvent event) {
151 RepositoryTreeNode node = (RepositoryTreeNode) ((IStructuredSelection) branchTree
152 .getSelection()).getFirstElement();
153 if (node.getType() != RepositoryTreeNodeType.REF
154 && node.getType() != RepositoryTreeNodeType.TAG)
155 branchTree.setExpandedState(node, !branchTree
156 .getExpandedState(node));
157 else if (confirmationBtn.isEnabled())
158 okPressed();
163 createCustomArea(parent);
165 String rawTitle = getTitle();
166 String title = NLS.bind(rawTitle, new Object[] { repo.getDirectory() });
168 setTitle(title);
169 setMessage(getMessageText());
170 getShell().setText(title);
172 applyDialogFont(parent);
174 return parent;
177 @Override
178 public void create() {
179 super.create();
181 List<RepositoryTreeNode> roots = new ArrayList<RepositoryTreeNode>();
182 roots.add(localBranches);
183 roots.add(remoteBranches);
184 roots.add(tags);
186 branchTree.setInput(roots);
188 try {
189 // initially, we mark the current head if it can be determined
190 String fullBranch = repo.getFullBranch();
191 if (!markRef(fullBranch))
192 // if we can't determine a branch, we just expand local branches
193 branchTree.expandToLevel(localBranches, 1);
194 } catch (IOException e) {
195 // ignore
199 private boolean markRef(String refName) {
200 // selects the entry specified by the name
201 if (refName == null)
202 return false;
204 RepositoryTreeNode node;
205 try {
206 if (refName.startsWith(Constants.R_HEADS)) {
207 Ref ref = this.repo.getRef(refName);
208 node = new RefNode(localBranches, this.repo, ref);
209 } else {
210 String mappedRef = Activator.getDefault().getRepositoryUtil()
211 .mapCommitToRef(this.repo, refName, false);
212 if (mappedRef != null
213 && mappedRef.startsWith(Constants.R_REMOTES)) {
214 Ref ref = this.repo.getRef(mappedRef);
215 node = new RefNode(remoteBranches, this.repo, ref);
216 } else if (mappedRef != null
217 && mappedRef.startsWith(Constants.R_TAGS)) {
218 Ref ref = this.repo.getRef(mappedRef);
219 node = new TagNode(tags, this.repo, ref);
220 } else {
221 return false;
224 } catch (IOException e) {
225 return false;
228 branchTree.setSelection(new StructuredSelection(node), true);
229 return true;
233 * @return the selected refName
235 public String getRefName() {
236 return this.selectedBranch;
239 @Override
240 protected void okPressed() {
241 this.selectedBranch = refNameFromDialog();
242 super.okPressed();
245 private String refNameFromDialog() {
246 IStructuredSelection sel = (IStructuredSelection) branchTree
247 .getSelection();
248 if (sel.size() != 1)
249 return null;
250 RepositoryTreeNode node = (RepositoryTreeNode) sel.getFirstElement();
251 if (node.getType() == RepositoryTreeNodeType.REF
252 || node.getType() == RepositoryTreeNodeType.TAG) {
253 return ((Ref) node.getObject()).getName();
255 return null;
258 private InputDialog getRefNameInputDialog(String prompt, final String refPrefix) {
259 InputDialog labelDialog = new InputDialog(
260 getShell(),
261 UIText.BranchSelectionDialog_QuestionNewBranchTitle,
262 prompt,
263 null, ValidationUtils.getRefNameInputValidator(repo, refPrefix));
264 labelDialog.setBlockOnOpen(true);
265 return labelDialog;
268 @Override
269 protected void createButtonsForButtonBar(Composite parent) {
270 newButton = new Button(parent, SWT.PUSH);
271 newButton.setFont(JFaceResources.getDialogFont());
272 newButton.setText(UIText.BranchSelectionDialog_NewBranch);
273 setButtonLayoutData(newButton);
274 ((GridLayout)parent.getLayout()).numColumns++;
276 renameButton = new Button(parent, SWT.PUSH);
277 renameButton.setFont(JFaceResources.getDialogFont());
278 renameButton.setText(UIText.BranchSelectionDialog_Rename);
279 setButtonLayoutData(renameButton);
280 ((GridLayout)parent.getLayout()).numColumns++;
282 renameButton.addSelectionListener(new SelectionAdapter() {
283 public void widgetSelected(SelectionEvent e) {
285 String refName = refNameFromDialog();
286 String refPrefix;
288 // the button should be disabled anyway, but we check again
289 if (refName.equals(Constants.HEAD))
290 return;
292 if (refName.startsWith(Constants.R_HEADS))
293 refPrefix = Constants.R_HEADS;
294 else if (refName.startsWith(Constants.R_REMOTES))
295 refPrefix = Constants.R_REMOTES;
296 else if (refName.startsWith(Constants.R_TAGS))
297 refPrefix = Constants.R_TAGS;
298 else {
299 // the button should be disabled anyway, but we check again
300 return;
303 String branchName = refName.substring(refPrefix.length());
305 InputDialog labelDialog = getRefNameInputDialog(NLS
306 .bind(
307 UIText.BranchSelectionDialog_QuestionNewBranchNameMessage,
308 branchName, refPrefix), refPrefix);
309 if (labelDialog.open() == Window.OK) {
310 String newRefName = refPrefix + labelDialog.getValue();
311 try {
312 RefRename renameRef = repo.renameRef(refName, newRefName);
313 if (renameRef.rename() != Result.RENAMED) {
314 reportError(
315 null,
316 UIText.BranchSelectionDialog_ErrorCouldNotRenameRef,
317 refName, newRefName, renameRef
318 .getResult());
320 branchTree.refresh();
321 markRef(newRefName);
322 } catch (Throwable e1) {
323 reportError(
325 UIText.BranchSelectionDialog_ErrorCouldNotRenameRef,
326 refName, newRefName, e1.getMessage());
331 newButton.addSelectionListener(new SelectionAdapter() {
333 public void widgetSelected(SelectionEvent e) {
334 // check what ref name the user selected, if any.
335 String refName = refNameFromDialog();
337 // the button should be disabled anyway, but we check again
338 if (refName.equals(Constants.HEAD))
339 return;
340 if (refName.startsWith(Constants.R_TAGS))
341 // the button should be disabled anyway, but we check again
342 return;
344 InputDialog labelDialog = getRefNameInputDialog(
346 .bind(
347 UIText.BranchSelectionDialog_QuestionNewBranchMessage,
348 refName, Constants.R_HEADS),
349 Constants.R_HEADS);
351 if (labelDialog.open() == Window.OK) {
352 String newRefName = Constants.R_HEADS + labelDialog.getValue();
353 RefUpdate updateRef;
354 try {
355 updateRef = repo.updateRef(newRefName);
356 Ref startRef = repo.getRef(refName);
357 ObjectId startAt = repo.resolve(refName);
358 String startBranch;
359 if (startRef != null)
360 startBranch = refName;
361 else
362 startBranch = startAt.name();
363 startBranch = repo.shortenRefName(startBranch);
364 updateRef.setNewObjectId(startAt);
365 updateRef.setRefLogMessage("branch: Created from " + startBranch, false); //$NON-NLS-1$
366 updateRef.update();
367 branchTree.refresh();
368 markRef(newRefName);
369 } catch (Throwable e1) {
370 reportError(
372 UIText.BranchSelectionDialog_ErrorCouldNotCreateNewRef,
373 newRefName);
378 confirmationBtn = createButton(parent, IDialogConstants.OK_ID,
379 UIText.BranchSelectionDialog_OkCheckout, true);
380 createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
382 // can't advance without a selection
383 confirmationBtn.setEnabled(!branchTree.getSelection().isEmpty());
387 * @return the message shown above the refs tree
389 protected String getMessageText() {
390 return UIText.BranchSelectionDialog_Refs;
394 * Subclasses may add UI elements
395 * @param parent
397 protected void createCustomArea(Composite parent) {
398 // do nothing
402 * Subclasses may change the title of the dialog
403 * @return the title of the dialog
405 protected String getTitle() {
406 return UIText.BranchSelectionDialog_TitleCheckout;
411 * @return if the confirmation button is enabled when a tag is selected
413 protected boolean canConfirmOnTag() {
414 return true;
417 @Override
418 protected int getShellStyle() {
419 return super.getShellStyle() | SWT.RESIZE;
422 private void reportError(Throwable e, String message, Object... args) {
423 String msg = NLS.bind(message, args);
424 Activator.handleError(msg, e, true);