1 /*******************************************************************************
2 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *******************************************************************************/
11 package org
.eclipse
.egit
.ui
.internal
.clone
;
14 import java
.io
.IOException
;
15 import java
.lang
.reflect
.InvocationTargetException
;
16 import java
.util
.ArrayList
;
17 import java
.util
.Collections
;
18 import java
.util
.Comparator
;
19 import java
.util
.List
;
21 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
22 import org
.eclipse
.core
.runtime
.IStatus
;
23 import org
.eclipse
.core
.runtime
.Status
;
24 import org
.eclipse
.egit
.core
.op
.ListRemoteOperation
;
25 import org
.eclipse
.egit
.ui
.Activator
;
26 import org
.eclipse
.egit
.ui
.UIText
;
27 import org
.eclipse
.egit
.ui
.internal
.components
.BaseWizardPage
;
28 import org
.eclipse
.egit
.ui
.internal
.components
.RepositorySelection
;
29 import org
.eclipse
.egit
.ui
.internal
.components
.RepositorySelectionPage
;
30 import org
.eclipse
.egit
.ui
.internal
.components
.SelectionChangeListener
;
31 import org
.eclipse
.jface
.dialogs
.ErrorDialog
;
32 import org
.eclipse
.jface
.dialogs
.IMessageProvider
;
33 import org
.eclipse
.jface
.operation
.IRunnableWithProgress
;
34 import org
.eclipse
.osgi
.util
.NLS
;
35 import org
.eclipse
.swt
.SWT
;
36 import org
.eclipse
.swt
.events
.SelectionAdapter
;
37 import org
.eclipse
.swt
.events
.SelectionEvent
;
38 import org
.eclipse
.swt
.layout
.GridData
;
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
.Label
;
44 import org
.eclipse
.swt
.widgets
.Table
;
45 import org
.eclipse
.swt
.widgets
.TableItem
;
46 import org
.eclipse
.jgit
.lib
.Constants
;
47 import org
.eclipse
.jgit
.lib
.Ref
;
48 import org
.eclipse
.jgit
.lib
.Repository
;
49 import org
.eclipse
.jgit
.transport
.URIish
;
51 class SourceBranchPage
extends BaseWizardPage
{
52 private final RepositorySelectionPage sourcePage
;
54 private RepositorySelection validatedRepoSelection
;
58 private List
<Ref
> availableRefs
= new ArrayList
<Ref
>();
60 private List
<Ref
> selectedRefs
= new ArrayList
<Ref
>();
62 private boolean sourceRepoEmpty
= false;
66 private Table refsTable
;
68 private String transportError
;
70 SourceBranchPage(final RepositorySelectionPage sp
) {
71 super(SourceBranchPage
.class.getName());
73 setTitle(UIText
.SourceBranchPage_title
);
74 setDescription(UIText
.SourceBranchPage_description
);
76 sourcePage
.addSelectionListener(new SelectionChangeListener() {
77 public void selectionChanged() {
78 if (!sourcePage
.selectionEquals(validatedRepoSelection
))
79 setPageComplete(false);
86 List
<Ref
> getSelectedBranches() {
87 return new ArrayList
<Ref
>(selectedRefs
);
94 boolean isSourceRepoEmpty() {
95 return sourceRepoEmpty
;
98 boolean isAllSelected() {
99 return availableRefs
.size() == selectedRefs
.size();
102 boolean selectionEquals(final List
<Ref
> selectedRefs
, final Ref head
) {
103 return this.selectedRefs
.equals(selectedRefs
) && this.head
== head
;
106 public void createControl(final Composite parent
) {
107 final Composite panel
= new Composite(parent
, SWT
.NULL
);
108 final GridLayout layout
= new GridLayout();
109 layout
.numColumns
= 1;
110 panel
.setLayout(layout
);
112 label
= new Label(panel
, SWT
.NONE
);
113 label
.setLayoutData(new GridData(SWT
.FILL
, SWT
.TOP
, true, false));
115 refsTable
= new Table(panel
, SWT
.CHECK
| SWT
.V_SCROLL
| SWT
.BORDER
);
116 refsTable
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
117 refsTable
.addSelectionListener(new SelectionAdapter() {
119 public void widgetSelected(final SelectionEvent e
) {
120 if (e
.detail
!= SWT
.CHECK
)
123 final TableItem tableItem
= (TableItem
) e
.item
;
124 final int i
= refsTable
.indexOf(tableItem
);
125 final Ref ref
= availableRefs
.get(i
);
127 if (tableItem
.getChecked()) {
128 int insertionPos
= 0;
129 for (int j
= 0; j
< i
; j
++) {
130 if (selectedRefs
.contains(availableRefs
.get(j
)))
133 selectedRefs
.add(insertionPos
, ref
);
135 selectedRefs
.remove(ref
);
137 notifySelectionChanged();
142 final Composite bPanel
= new Composite(panel
, SWT
.NONE
);
143 bPanel
.setLayout(new RowLayout());
144 final Button selectB
;
145 selectB
= new Button(bPanel
, SWT
.PUSH
);
146 selectB
.setText(UIText
.SourceBranchPage_selectAll
);
147 selectB
.addSelectionListener(new SelectionAdapter() {
148 public void widgetSelected(final SelectionEvent e
) {
149 for (int i
= 0; i
< refsTable
.getItemCount(); i
++)
150 refsTable
.getItem(i
).setChecked(true);
151 selectedRefs
.clear();
152 selectedRefs
.addAll(availableRefs
);
153 notifySelectionChanged();
157 final Button unselectB
= new Button(bPanel
, SWT
.PUSH
);
158 unselectB
.setText(UIText
.SourceBranchPage_selectNone
);
159 unselectB
.addSelectionListener(new SelectionAdapter() {
160 public void widgetSelected(final SelectionEvent e
) {
161 for (int i
= 0; i
< refsTable
.getItemCount(); i
++)
162 refsTable
.getItem(i
).setChecked(false);
163 selectedRefs
.clear();
164 notifySelectionChanged();
168 bPanel
.setLayoutData(new GridData(SWT
.FILL
, SWT
.TOP
, true, false));
170 addSelectionListener(new SelectionChangeListener() {
171 public void selectionChanged() {
172 selectB
.setEnabled(selectedRefs
.size() != availableRefs
.size());
173 unselectB
.setEnabled(selectedRefs
.size() != 0);
182 public void setVisible(final boolean visible
) {
185 super.setVisible(visible
);
189 * Check internal state for page completion status. This method should be
190 * called only when all necessary data from previous form is available.
192 private void checkPage() {
193 if (transportError
!= null) {
194 setErrorMessage(transportError
);
195 setPageComplete(false);
199 if (isSourceRepoEmpty()) {
200 setMessage(UIText
.SourceBranchPage_repoEmpty
, IMessageProvider
.WARNING
);
201 setPageComplete(true);
205 if ( getSelectedBranches().isEmpty()) {
206 setErrorMessage(UIText
.SourceBranchPage_errorBranchRequired
);
207 setPageComplete(false);
211 setErrorMessage(null);
212 setPageComplete(true);
215 private void revalidate() {
216 if (sourcePage
.selectionEquals(validatedRepoSelection
)) {
217 // URI hasn't changed, no need to refill the page with new data
222 final RepositorySelection newRepoSelection
= sourcePage
.getSelection();
223 label
.setText(NLS
.bind(UIText
.SourceBranchPage_branchList
,
224 newRepoSelection
.getURI().toString()));
225 label
.getParent().layout();
227 validatedRepoSelection
= null;
228 transportError
= null;
230 availableRefs
.clear();
231 selectedRefs
.clear();
232 refsTable
.removeAll();
233 setPageComplete(false);
234 setErrorMessage(null);
235 label
.getDisplay().asyncExec(new Runnable() {
237 revalidateImpl(newRepoSelection
);
242 private void revalidateImpl(final RepositorySelection newRepoSelection
) {
243 if (label
.isDisposed() || !isCurrentPage())
246 final ListRemoteOperation listRemoteOp
;
248 final URIish uri
= newRepoSelection
.getURI();
249 final Repository db
= new Repository(new File("/tmp")); //$NON-NLS-1$
250 listRemoteOp
= new ListRemoteOperation(db
, uri
);
251 getContainer().run(true, true, new IRunnableWithProgress() {
252 public void run(IProgressMonitor monitor
)
253 throws InvocationTargetException
, InterruptedException
{
254 listRemoteOp
.run(monitor
);
257 } catch (InvocationTargetException e
) {
258 Throwable why
= e
.getCause();
259 transportError(why
.getMessage());
260 ErrorDialog
.openError(getShell(),
261 UIText
.SourceBranchPage_transportError
,
262 UIText
.SourceBranchPage_cannotListBranches
, new Status(
263 IStatus
.ERROR
, Activator
.getPluginId(), 0, why
264 .getMessage(), why
.getCause()));
266 } catch (IOException e
) {
267 transportError(UIText
.SourceBranchPage_cannotCreateTemp
);
269 } catch (InterruptedException e
) {
270 transportError(UIText
.SourceBranchPage_remoteListingCancelled
);
274 final Ref idHEAD
= listRemoteOp
.getRemoteRef(Constants
.HEAD
);
276 for (final Ref r
: listRemoteOp
.getRemoteRefs()) {
277 final String n
= r
.getName();
278 if (!n
.startsWith(Constants
.R_HEADS
))
280 availableRefs
.add(r
);
281 if (idHEAD
== null || head
!= null)
283 if (r
.getObjectId().equals(idHEAD
.getObjectId()))
286 Collections
.sort(availableRefs
, new Comparator
<Ref
>() {
287 public int compare(final Ref o1
, final Ref o2
) {
288 return o1
.getName().compareTo(o2
.getName());
291 if (idHEAD
!= null && head
== null) {
293 availableRefs
.add(0, idHEAD
);
296 validatedRepoSelection
= newRepoSelection
;
297 for (final Ref r
: availableRefs
) {
298 String n
= r
.getName();
299 if (n
.startsWith(Constants
.R_HEADS
))
300 n
= n
.substring(Constants
.R_HEADS
.length());
301 final TableItem ti
= new TableItem(refsTable
, SWT
.NONE
);
306 if (availableRefs
.size() == 0)
307 sourceRepoEmpty
= true;
308 notifySelectionChanged();
312 private void transportError(final String msg
) {
313 transportError
= msg
;