Clone: Handle cancel in clone dialog specially
[egit/zawir.git] / org.spearce.egit.ui / src / org / spearce / egit / ui / internal / clone / SourceBranchPage.java
blob615be32eec9b08ebf8fd807a3f3ee3057e2f6a9a
1 /*******************************************************************************
2 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
5 * All rights reserved. This program and the accompanying materials
6 * are made available under the terms of the Eclipse Public License v1.0
7 * See LICENSE for the full license text, also available.
8 *******************************************************************************/
9 package org.spearce.egit.ui.internal.clone;
11 import java.io.File;
12 import java.lang.reflect.InvocationTargetException;
13 import java.net.URISyntaxException;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.Comparator;
18 import java.util.List;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.NullProgressMonitor;
23 import org.eclipse.core.runtime.OperationCanceledException;
24 import org.eclipse.core.runtime.Status;
25 import org.eclipse.jface.dialogs.ErrorDialog;
26 import org.eclipse.jface.operation.IRunnableWithProgress;
27 import org.eclipse.jface.wizard.WizardPage;
28 import org.eclipse.osgi.util.NLS;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.events.SelectionEvent;
31 import org.eclipse.swt.events.SelectionListener;
32 import org.eclipse.swt.layout.GridData;
33 import org.eclipse.swt.layout.GridLayout;
34 import org.eclipse.swt.layout.RowLayout;
35 import org.eclipse.swt.widgets.Button;
36 import org.eclipse.swt.widgets.Composite;
37 import org.eclipse.swt.widgets.Event;
38 import org.eclipse.swt.widgets.Label;
39 import org.eclipse.swt.widgets.Listener;
40 import org.eclipse.swt.widgets.Table;
41 import org.eclipse.swt.widgets.TableItem;
42 import org.spearce.egit.ui.Activator;
43 import org.spearce.egit.ui.UIIcons;
44 import org.spearce.egit.ui.UIText;
45 import org.spearce.jgit.lib.Constants;
46 import org.spearce.jgit.lib.Ref;
47 import org.spearce.jgit.lib.Repository;
48 import org.spearce.jgit.transport.FetchConnection;
49 import org.spearce.jgit.transport.Transport;
50 import org.spearce.jgit.transport.URIish;
52 class SourceBranchPage extends WizardPage {
53 private final List<BranchChangeListener> branchChangeListeners;
55 private final CloneSourcePage sourcePage;
57 private URIish validated;
59 private Ref head;
61 private List<Ref> available = Collections.<Ref> emptyList();
63 private Label label;
65 private Table availTable;
67 private boolean allSelected;
69 private String transportError;
71 SourceBranchPage(final CloneSourcePage sp) {
72 super(SourceBranchPage.class.getName());
73 sourcePage = sp;
74 setTitle(UIText.CloneSourcePage_title);
75 setImageDescriptor(UIIcons.WIZBAN_IMPORT_REPO);
76 sourcePage.addURIishChangeListener(new URIishChangeListener() {
77 public void uriishChanged(final URIish newURI) {
78 if (newURI == null || !newURI.equals(validated))
79 setPageComplete(false);
81 });
82 branchChangeListeners = new ArrayList<BranchChangeListener>(3);
85 void addBranchChangeListener(final BranchChangeListener l) {
86 branchChangeListeners.add(l);
89 Collection<Ref> getSelectedBranches() {
90 allSelected = true;
91 final ArrayList<Ref> r = new ArrayList<Ref>(available.size());
92 for (int i = 0; i < available.size(); i++) {
93 if (availTable.getItem(i).getChecked())
94 r.add(available.get(i));
95 else
96 allSelected = false;
98 return r;
101 Ref getHEAD() {
102 return head;
105 boolean isAllSelected() {
106 return allSelected;
109 public void createControl(final Composite parent) {
110 final Composite panel = new Composite(parent, SWT.NULL);
111 final GridLayout layout = new GridLayout();
112 layout.numColumns = 1;
113 panel.setLayout(layout);
115 label = new Label(panel, SWT.NONE);
116 label.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
118 availTable = new Table(panel, SWT.CHECK | SWT.V_SCROLL | SWT.BORDER);
119 availTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
120 availTable.addListener(SWT.Selection, new Listener() {
121 public void handleEvent(final Event event) {
122 if (event.detail == SWT.CHECK) {
123 notifyChanged();
124 setPageComplete(isPageComplete());
129 final Composite bPanel = new Composite(panel, SWT.NONE);
130 bPanel.setLayout(new RowLayout());
131 Button b;
132 b = new Button(bPanel, SWT.PUSH);
133 b.setText(UIText.SourceBranchPage_selectAll);
134 b.addSelectionListener(new SelectionListener() {
135 public void widgetDefaultSelected(SelectionEvent e) {
136 // Do nothing.
139 public void widgetSelected(SelectionEvent e) {
140 for (int i = 0; i < availTable.getItemCount(); i++)
141 availTable.getItem(i).setChecked(true);
142 notifyChanged();
143 setPageComplete(isPageComplete());
146 b = new Button(bPanel, SWT.PUSH);
147 b.setText(UIText.SourceBranchPage_selectNone);
148 b.addSelectionListener(new SelectionListener() {
149 public void widgetDefaultSelected(SelectionEvent e) {
150 // Do nothing.
153 public void widgetSelected(SelectionEvent e) {
154 for (int i = 0; i < availTable.getItemCount(); i++)
155 availTable.getItem(i).setChecked(false);
156 notifyChanged();
157 setPageComplete(isPageComplete());
160 bPanel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
162 setControl(panel);
163 setPageComplete(false);
166 @Override
167 public void setVisible(final boolean visible) {
168 if (visible)
169 revalidate();
170 super.setVisible(visible);
173 @Override
174 public boolean isPageComplete() {
175 if (transportError != null) {
176 setErrorMessage(transportError);
177 return false;
180 if (getSelectedBranches().isEmpty()) {
181 setErrorMessage(UIText.SourceBranchPage_errorBranchRequired);
182 return false;
185 setErrorMessage(null);
186 return true;
189 private void revalidate() {
190 final URIish newURI;
191 try {
192 newURI = sourcePage.getURI();
193 } catch (URISyntaxException e) {
194 transportError(e.getReason());
195 return;
198 label.setText(NLS.bind(UIText.SourceBranchPage_branchList, newURI
199 .toString()));
200 label.getParent().layout();
202 if (newURI.equals(validated)) {
203 setPageComplete(isPageComplete());
204 return;
207 setErrorMessage(null);
208 setPageComplete(false);
209 transportError = null;
210 head = null;
211 available = new ArrayList<Ref>();
212 availTable.removeAll();
213 allSelected = false;
214 label.getDisplay().asyncExec(new Runnable() {
215 public void run() {
216 revalidateImpl(newURI);
221 private void revalidateImpl(final URIish newURI) {
222 if (label.isDisposed() || !isCurrentPage())
223 return;
224 try {
225 getContainer().run(true, true, new IRunnableWithProgress() {
226 public void run(final IProgressMonitor pm)
227 throws InvocationTargetException, InterruptedException {
228 final IProgressMonitor monitor;
229 if (pm == null)
230 monitor = new NullProgressMonitor();
231 else
232 monitor = pm;
233 try {
234 final Repository db = new Repository(new File("/tmp"));
235 final Transport tn = Transport.open(db, newURI);
236 final Collection<Ref> adv;
237 final FetchConnection fn = tn.openFetch();
238 try {
239 adv = fn.getRefs();
240 } finally {
241 fn.close();
244 final Ref idHEAD = fn.getRef(Constants.HEAD);
245 head = null;
246 for (final Ref r : adv) {
247 final String n = r.getName();
248 if (!n.startsWith(Constants.HEADS_PREFIX + "/"))
249 continue;
250 available.add(r);
251 if (idHEAD == null || head != null)
252 continue;
253 if (r.getObjectId().equals(idHEAD.getObjectId()))
254 head = r;
256 Collections.sort(available, new Comparator<Ref>() {
257 public int compare(final Ref o1, final Ref o2) {
258 return o1.getName().compareTo(o2.getName());
261 if (idHEAD != null && head == null) {
262 head = idHEAD;
263 available.add(0, idHEAD);
265 } catch (Exception err) {
266 throw new InvocationTargetException(err);
268 monitor.done();
271 } catch (InvocationTargetException e) {
272 Throwable why = e.getCause();
273 if ((why instanceof OperationCanceledException)) {
274 transportError(UIText.SourceBranchPage_remoteListingCancelled);
275 return;
276 } else {
277 ErrorDialog.openError(getShell(),
278 UIText.SourceBranchPage_transportError,
279 UIText.SourceBranchPage_cannotListBranches, new Status(
280 IStatus.ERROR, Activator.getPluginId(), 0, why
281 .getMessage(), why.getCause()));
282 transportError(why.getMessage());
284 return;
285 } catch (InterruptedException e) {
286 transportError(UIText.SourceBranchPage_interrupted);
287 return;
290 validated = newURI;
291 allSelected = true;
292 for (final Ref r : available) {
293 String n = r.getName();
294 if (n.startsWith(Constants.HEADS_PREFIX + "/"))
295 n = n.substring((Constants.HEADS_PREFIX + "/").length());
296 final TableItem ti = new TableItem(availTable, SWT.NONE);
297 ti.setText(n);
298 ti.setChecked(true);
300 notifyChanged();
301 setErrorMessage(null);
302 setPageComplete(isPageComplete());
305 private void transportError(final String msg) {
306 transportError = msg;
307 setErrorMessage(msg);
308 setPageComplete(false);
311 private void notifyChanged() {
312 for (final BranchChangeListener l : branchChangeListeners)
313 l.branchesChanged();