1 /*******************************************************************************
2 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
3 * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com.dewire.com>
4 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
5 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
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
.Collections
;
17 import java
.util
.List
;
19 import org
.eclipse
.egit
.core
.op
.ResetOperation
.ResetType
;
20 import org
.eclipse
.egit
.ui
.Activator
;
21 import org
.eclipse
.egit
.ui
.UIText
;
22 import org
.eclipse
.jface
.dialogs
.Dialog
;
23 import org
.eclipse
.jface
.dialogs
.IDialogConstants
;
24 import org
.eclipse
.jface
.dialogs
.IInputValidator
;
25 import org
.eclipse
.jface
.dialogs
.InputDialog
;
26 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
27 import org
.eclipse
.jface
.layout
.GridDataFactory
;
28 import org
.eclipse
.jface
.layout
.GridLayoutFactory
;
29 import org
.eclipse
.jface
.resource
.JFaceResources
;
30 import org
.eclipse
.jface
.window
.Window
;
31 import org
.eclipse
.osgi
.util
.NLS
;
32 import org
.eclipse
.swt
.SWT
;
33 import org
.eclipse
.swt
.events
.DisposeEvent
;
34 import org
.eclipse
.swt
.events
.DisposeListener
;
35 import org
.eclipse
.swt
.events
.SelectionEvent
;
36 import org
.eclipse
.swt
.events
.SelectionListener
;
37 import org
.eclipse
.swt
.graphics
.Font
;
38 import org
.eclipse
.swt
.graphics
.FontData
;
39 import org
.eclipse
.swt
.layout
.GridLayout
;
40 import org
.eclipse
.swt
.layout
.RowLayout
;
41 import org
.eclipse
.swt
.widgets
.Button
;
42 import org
.eclipse
.swt
.widgets
.Composite
;
43 import org
.eclipse
.swt
.widgets
.Event
;
44 import org
.eclipse
.swt
.widgets
.Group
;
45 import org
.eclipse
.swt
.widgets
.Label
;
46 import org
.eclipse
.swt
.widgets
.Listener
;
47 import org
.eclipse
.swt
.widgets
.Shell
;
48 import org
.eclipse
.swt
.widgets
.Tree
;
49 import org
.eclipse
.swt
.widgets
.TreeItem
;
50 import org
.eclipse
.jgit
.lib
.Constants
;
51 import org
.eclipse
.jgit
.lib
.ObjectId
;
52 import org
.eclipse
.jgit
.lib
.Ref
;
53 import org
.eclipse
.jgit
.lib
.RefRename
;
54 import org
.eclipse
.jgit
.lib
.RefUpdate
;
55 import org
.eclipse
.jgit
.lib
.Repository
;
56 import org
.eclipse
.jgit
.lib
.RefUpdate
.Result
;
59 * The branch and reset selection dialog
62 public class BranchSelectionDialog
extends Dialog
{
63 private final Repository repo
;
65 private boolean showResetType
= true;
68 * Construct a dialog to select a branch to reset to or check out
72 public BranchSelectionDialog(Shell parentShell
, Repository repo
) {
78 * Pre-set whether or present a reset or checkout dialog
81 public void setShowResetType(boolean show
) {
82 this.showResetType
= show
;
85 private Composite parent
;
87 private Tree branchTree
;
90 protected Composite
createDialogArea(Composite base
) {
91 parent
= (Composite
) super.createDialogArea(base
);
92 parent
.setLayout(GridLayoutFactory
.swtDefaults().create());
93 new Label(parent
, SWT
.NONE
).setText(UIText
.BranchSelectionDialog_Refs
);
94 branchTree
= new Tree(parent
, SWT
.BORDER
);
95 branchTree
.setLayoutData(GridDataFactory
.fillDefaults().grab(true,true).hint(500, 300).create());
101 String rawTitle
= showResetType ? UIText
.BranchSelectionDialog_TitleReset
102 : UIText
.BranchSelectionDialog_TitleCheckout
;
104 NLS
.bind(rawTitle
, new Object
[] { repo
.getDirectory() }));
107 fillTreeWithBranches(null);
108 } catch (Throwable e
) {
109 Activator
.logError(UIText
.BranchSelectionDialog_ErrorCouldNotRefresh
, e
);
115 private void buildResetGroup() {
116 Group g
= new Group(parent
, SWT
.NONE
);
117 g
.setText(UIText
.BranchSelectionDialog_ResetType
);
118 g
.setLayoutData(GridDataFactory
.swtDefaults().align(SWT
.CENTER
, SWT
.CENTER
).create());
119 g
.setLayout(new RowLayout(SWT
.VERTICAL
));
121 Button soft
= new Button(g
, SWT
.RADIO
);
122 soft
.setText(UIText
.BranchSelectionDialog_ResetTypeSoft
);
123 soft
.addListener(SWT
.Selection
, new Listener() {
124 public void handleEvent(Event event
) {
125 resetType
= ResetType
.SOFT
;
129 Button medium
= new Button(g
, SWT
.RADIO
);
130 medium
.setSelection(true);
131 medium
.setText(UIText
.BranchSelectionDialog_ResetTypeMixed
);
132 medium
.addListener(SWT
.Selection
, new Listener() {
133 public void handleEvent(Event event
) {
134 resetType
= ResetType
.MIXED
;
138 Button hard
= new Button(g
, SWT
.RADIO
);
139 hard
.setText(UIText
.BranchSelectionDialog_ResetTypeHard
);
140 hard
.addListener(SWT
.Selection
, new Listener() {
141 public void handleEvent(Event event
) {
142 resetType
= ResetType
.HARD
;
147 private void fillTreeWithBranches(String select
) throws IOException
{
148 String branch
= repo
.getFullBranch();
149 List
<String
> branches
= new ArrayList
<String
>(repo
.getAllRefs()
151 Collections
.sort(branches
);
153 TreeItem curItem
= null;
154 TreeItem curSubItem
= null;
155 String curPrefix
= null;
156 String curSubPrefix
= null;
157 TreeItem itemToSelect
= null;
159 for (String ref
: branches
) {
160 String shortName
= ref
;
161 if (ref
.startsWith(Constants
.R_HEADS
)) {
162 shortName
= ref
.substring(11);
163 if (!Constants
.R_HEADS
.equals(curPrefix
)) {
164 curPrefix
= Constants
.R_HEADS
;
167 curItem
= new TreeItem(branchTree
, SWT
.NONE
);
168 curItem
.setText(UIText
.BranchSelectionDialog_LocalBranches
);
170 } else if (ref
.startsWith(Constants
.R_REMOTES
)) {
171 shortName
= ref
.substring(13);
172 if (!Constants
.R_REMOTES
.equals(curPrefix
)) {
173 curPrefix
= Constants
.R_REMOTES
;
174 curItem
= new TreeItem(branchTree
, SWT
.NONE
);
175 curItem
.setText(UIText
.BranchSelectionDialog_RemoteBranches
);
180 int slashPos
= shortName
.indexOf("/"); //$NON-NLS-1$
182 String remoteName
= shortName
.substring(0, slashPos
);
183 shortName
= shortName
.substring(slashPos
+1);
184 if (!remoteName
.equals(curSubPrefix
)) {
185 curSubItem
= new TreeItem(curItem
, SWT
.NONE
);
186 curSubItem
.setText(remoteName
);
187 curSubPrefix
= remoteName
;
193 } else if (ref
.startsWith(Constants
.R_TAGS
)) {
194 shortName
= ref
.substring(10);
195 if (!Constants
.R_TAGS
.equals(curPrefix
)) {
196 curPrefix
= Constants
.R_TAGS
;
199 curItem
= new TreeItem(branchTree
, SWT
.NONE
);
200 curItem
.setText(UIText
.BranchSelectionDialog_Tags
);
205 item
= new TreeItem(branchTree
, SWT
.NONE
);
206 else if (curSubItem
== null)
207 item
= new TreeItem(curItem
, SWT
.NONE
);
208 else item
= new TreeItem(curSubItem
, SWT
.NONE
);
210 if (ref
.equals(branch
)) {
211 item
.setText(shortName
+ UIText
.BranchSelectionDialog_BranchSuffix_Current
);
212 FontData fd
= item
.getFont().getFontData()[0];
213 fd
.setStyle(fd
.getStyle() | SWT
.BOLD
);
214 final Font f
= new Font(getShell().getDisplay(), fd
);
216 item
.addDisposeListener(new DisposeListener() {
217 public void widgetDisposed(DisposeEvent e
) {
221 branchTree
.showItem(item
);
223 else item
.setText(shortName
);
224 if (ref
.equals(select
))
226 branchTree
.setLinesVisible(true);
228 if (itemToSelect
!= null) {
229 branchTree
.select(itemToSelect
);
230 branchTree
.showItem(itemToSelect
);
234 private String refName
= null;
237 * @return Selected ref
239 public String
getRefName() {
243 private ResetType resetType
= ResetType
.MIXED
;
246 * @return Type of Reset
248 public ResetType
getResetType() {
253 protected void okPressed() {
255 if (refName
== null) {
256 MessageDialog
.openWarning(getShell(),
257 UIText
.BranchSelectionDialog_NoBranchSeletectTitle
,
258 UIText
.BranchSelectionDialog_NoBranchSeletectMessage
);
263 if (resetType
== ResetType
.HARD
) {
264 if (!MessageDialog
.openQuestion(getShell(),
265 UIText
.BranchSelectionDialog_ReallyResetTitle
,
266 UIText
.BranchSelectionDialog_ReallyResetMessage
)) {
275 private void refNameFromDialog() {
276 TreeItem
[] selection
= branchTree
.getSelection();
278 if (selection
!= null && selection
.length
> 0) {
279 TreeItem item
= selection
[0];
280 refName
= (String
) item
.getData();
284 private InputDialog
getRefNameInputDialog(String prompt
) {
285 InputDialog labelDialog
= new InputDialog(
287 UIText
.BranchSelectionDialog_QuestionNewBranchTitle
,
289 null, new IInputValidator() {
290 public String
isValid(String newText
) {
291 String testFor
= Constants
.R_HEADS
+ newText
;
293 if (repo
.resolve(testFor
) != null)
294 return UIText
.BranchSelectionDialog_ErrorAlreadyExists
;
295 } catch (IOException e1
) {
296 Activator
.logError(NLS
.bind(
297 UIText
.BranchSelectionDialog_ErrorCouldNotResolve
, testFor
), e1
);
298 return e1
.getMessage();
300 if (!Repository
.isValidRefName(testFor
))
301 return UIText
.BranchSelectionDialog_ErrorInvalidRefName
;
305 labelDialog
.setBlockOnOpen(true);
310 protected void createButtonsForButtonBar(Composite parent
) {
311 if (!showResetType
) {
312 Button newButton
= new Button(parent
, SWT
.PUSH
);
313 newButton
.setFont(JFaceResources
.getDialogFont());
314 newButton
.setText(UIText
.BranchSelectionDialog_NewBranch
);
315 ((GridLayout
)parent
.getLayout()).numColumns
++;
316 Button renameButton
= new Button(parent
, SWT
.PUSH
);
317 renameButton
.setText(UIText
.BranchSelectionDialog_Rename
);
318 renameButton
.addSelectionListener(new SelectionListener() {
319 public void widgetSelected(SelectionEvent e
) {
320 // check what ref name the user selected, if any.
324 if (refName
.startsWith(Constants
.R_HEADS
))
325 branchName
= refName
.substring(Constants
.R_HEADS
.length());
327 branchName
= refName
;
328 InputDialog labelDialog
= getRefNameInputDialog(NLS
330 UIText
.BranchSelectionDialog_QuestionNewBranchNameMessage
,
332 if (labelDialog
.open() == Window
.OK
) {
333 String newRefName
= Constants
.R_HEADS
+ labelDialog
.getValue();
335 RefRename renameRef
= repo
.renameRef(refName
, newRefName
);
336 if (renameRef
.rename() != Result
.RENAMED
) {
339 UIText
.BranchSelectionDialog_BranchSelectionDialog_RenamedFailedTitle
,
340 UIText
.BranchSelectionDialog_ErrorCouldNotRenameRef
,
341 refName
, newRefName
, renameRef
344 } catch (Throwable e1
) {
347 UIText
.BranchSelectionDialog_BranchSelectionDialog_RenamedFailedTitle
,
348 UIText
.BranchSelectionDialog_ErrorCouldNotRenameRef
,
349 refName
, newRefName
, e1
.getMessage());
352 branchTree
.removeAll();
353 fillTreeWithBranches(newRefName
);
354 } catch (Throwable e1
) {
357 UIText
.BranchSelectionDialog_BranchSelectionDialog_RenamedFailedTitle
,
358 UIText
.BranchSelectionDialog_ErrorCouldNotRefreshBranchList
);
362 public void widgetDefaultSelected(SelectionEvent e
) {
366 newButton
.addSelectionListener(new SelectionListener() {
368 public void widgetSelected(SelectionEvent e
) {
369 // check what ref name the user selected, if any.
372 InputDialog labelDialog
= getRefNameInputDialog(UIText
.BranchSelectionDialog_QuestionNewBranchNameMessage
);
373 if (labelDialog
.open() == Window
.OK
) {
374 String newRefName
= Constants
.R_HEADS
+ labelDialog
.getValue();
377 updateRef
= repo
.updateRef(newRefName
);
378 Ref startRef
= repo
.getRef(refName
);
381 startAt
= repo
.resolve(Constants
.HEAD
);
383 startAt
= repo
.resolve(refName
);
385 if (startRef
!= null)
386 startBranch
= refName
;
388 startBranch
= startAt
.name();
389 startBranch
= repo
.shortenRefName(startBranch
);
390 updateRef
.setNewObjectId(startAt
);
391 updateRef
.setRefLogMessage("branch: Created from " + startBranch
, false); //$NON-NLS-1$
393 } catch (Throwable e1
) {
396 UIText
.BranchSelectionDialog_BranchSelectionDialog_CreateFailedTitle
,
397 UIText
.BranchSelectionDialog_ErrorCouldNotCreateNewRef
,
401 branchTree
.removeAll();
402 fillTreeWithBranches(newRefName
);
403 } catch (Throwable e1
) {
405 UIText
.BranchSelectionDialog_BranchSelectionDialog_CreateFailedTitle
,
406 UIText
.BranchSelectionDialog_ErrorCouldNotRefreshBranchList
);
412 public void widgetDefaultSelected(SelectionEvent e
) {
417 createButton(parent
, IDialogConstants
.OK_ID
,
418 showResetType ? UIText
.BranchSelectionDialog_OkReset
419 : UIText
.BranchSelectionDialog_OkCheckout
, true);
420 createButton(parent
, IDialogConstants
.CANCEL_ID
, IDialogConstants
.CANCEL_LABEL
, false);
424 protected int getShellStyle() {
425 return super.getShellStyle() | SWT
.RESIZE
;
428 private void reportError(Throwable e
, String title
, String message
,
430 String msg
= NLS
.bind(message
, args
);
431 MessageDialog
.openError(getShell(), title
, msg
);
432 Activator
.logError(msg
, e
);