Git Repositories View: add CollapseAll action
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / clone / CloneDestinationPage.java
bloba8491fd87ebc5611231ea291fbc0dcdaec9460a3
1 /*******************************************************************************
2 * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
5 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.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.clone;
14 import java.io.File;
15 import java.util.List;
17 import org.eclipse.core.resources.ResourcesPlugin;
18 import org.eclipse.egit.ui.UIText;
19 import org.eclipse.egit.ui.internal.components.RepositorySelection;
20 import org.eclipse.egit.ui.internal.components.RepositorySelectionPage;
21 import org.eclipse.egit.ui.internal.components.SelectionChangeListener;
22 import org.eclipse.jface.wizard.WizardPage;
23 import org.eclipse.osgi.util.NLS;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.events.ModifyEvent;
26 import org.eclipse.swt.events.ModifyListener;
27 import org.eclipse.swt.events.SelectionAdapter;
28 import org.eclipse.swt.events.SelectionEvent;
29 import org.eclipse.swt.layout.GridData;
30 import org.eclipse.swt.layout.GridLayout;
31 import org.eclipse.swt.widgets.Button;
32 import org.eclipse.swt.widgets.Combo;
33 import org.eclipse.swt.widgets.Composite;
34 import org.eclipse.swt.widgets.FileDialog;
35 import org.eclipse.swt.widgets.Group;
36 import org.eclipse.swt.widgets.Label;
37 import org.eclipse.swt.widgets.Text;
38 import org.eclipse.jgit.lib.Constants;
39 import org.eclipse.jgit.lib.Ref;
41 /**
42 * Wizard page that allows the user entering the location of a repository to be
43 * cloned.
45 class CloneDestinationPage extends WizardPage {
46 private final RepositorySelectionPage sourcePage;
48 private final SourceBranchPage branchPage;
50 private RepositorySelection validatedRepoSelection;
52 private List<Ref> validatedSelectedBranches;
54 private Ref validatedHEAD;
56 private Combo initialBranch;
58 private Text directoryText;
60 private Text remoteText;
62 Button showImportWizard;
64 String alreadyClonedInto;
66 CloneDestinationPage(final RepositorySelectionPage sp,
67 final SourceBranchPage bp) {
68 super(CloneDestinationPage.class.getName());
69 sourcePage = sp;
70 branchPage = bp;
71 setTitle(UIText.CloneDestinationPage_title);
73 final SelectionChangeListener listener = new SelectionChangeListener() {
74 public void selectionChanged() {
75 checkPreviousPagesSelections();
78 sourcePage.addSelectionListener(listener);
79 branchPage.addSelectionListener(listener);
82 public void createControl(final Composite parent) {
83 final Composite panel = new Composite(parent, SWT.NULL);
84 final GridLayout layout = new GridLayout();
85 layout.numColumns = 1;
86 panel.setLayout(layout);
88 createDestinationGroup(panel);
89 createConfigGroup(panel);
90 createWorkbenchGroup(panel);
91 setControl(panel);
92 checkPage();
95 @Override
96 public void setVisible(final boolean visible) {
97 if (visible) {
98 if (branchPage.isSourceRepoEmpty()) {
99 initialBranch.setEnabled(false);
100 showImportWizard.setSelection(false);
101 showImportWizard.setEnabled(false);
103 revalidate();
105 super.setVisible(visible);
106 if (visible)
107 directoryText.setFocus();
110 private void checkPreviousPagesSelections() {
111 if (!sourcePage.selectionEquals(validatedRepoSelection)
112 || !branchPage.selectionEquals(validatedSelectedBranches,
113 validatedHEAD))
114 setPageComplete(false);
115 else
116 checkPage();
119 private void createDestinationGroup(final Composite parent) {
120 final Group g = createGroup(parent,
121 UIText.CloneDestinationPage_groupDestination);
123 newLabel(g, UIText.CloneDestinationPage_promptDirectory + ":"); //$NON-NLS-1$
124 final Composite p = new Composite(g, SWT.NONE);
125 final GridLayout grid = new GridLayout();
126 grid.numColumns = 2;
127 p.setLayout(grid);
128 p.setLayoutData(createFieldGridData());
129 directoryText = new Text(p, SWT.BORDER);
130 directoryText.setLayoutData(createFieldGridData());
131 directoryText.addModifyListener(new ModifyListener() {
132 public void modifyText(final ModifyEvent e) {
133 checkPage();
136 final Button b = new Button(p, SWT.PUSH);
137 b.setText(UIText.CloneDestinationPage_browseButton);
138 b.addSelectionListener(new SelectionAdapter() {
139 public void widgetSelected(final SelectionEvent e) {
140 final FileDialog d;
142 d = new FileDialog(getShell(), SWT.APPLICATION_MODAL | SWT.SAVE);
143 if (directoryText.getText().length() > 0) {
144 final File file = new File(directoryText.getText())
145 .getAbsoluteFile();
146 d.setFilterPath(file.getParent());
147 d.setFileName(file.getName());
149 final String r = d.open();
150 if (r != null)
151 directoryText.setText(r);
155 newLabel(g, UIText.CloneDestinationPage_promptInitialBranch + ":"); //$NON-NLS-1$
156 initialBranch = new Combo(g, SWT.DROP_DOWN | SWT.READ_ONLY);
157 initialBranch.setLayoutData(createFieldGridData());
158 initialBranch.addSelectionListener(new SelectionAdapter() {
159 @Override
160 public void widgetSelected(final SelectionEvent e) {
161 checkPage();
166 private void createConfigGroup(final Composite parent) {
167 final Group g = createGroup(parent,
168 UIText.CloneDestinationPage_groupConfiguration);
170 newLabel(g, UIText.CloneDestinationPage_promptRemoteName + ":"); //$NON-NLS-1$
171 remoteText = new Text(g, SWT.BORDER);
172 remoteText.setText(Constants.DEFAULT_REMOTE_NAME);
173 remoteText.setLayoutData(createFieldGridData());
174 remoteText.addModifyListener(new ModifyListener() {
175 public void modifyText(ModifyEvent e) {
176 checkPage();
181 private void createWorkbenchGroup(Composite parent) {
182 final Group g = createGroup(parent, UIText.CloneDestinationPage_workspaceImport);
183 showImportWizard = new Button(g, SWT.CHECK);
184 showImportWizard.setSelection(true);
185 showImportWizard.setText(UIText.CloneDestinationPage_importProjectsAfterClone);
186 showImportWizard.setLayoutData(createFieldGridData());
187 showImportWizard.addSelectionListener(new SelectionAdapter() {
188 @Override
189 public void widgetSelected(SelectionEvent e) {
190 checkPage();
195 private static Group createGroup(final Composite parent, final String text) {
196 final Group g = new Group(parent, SWT.NONE);
197 final GridLayout layout = new GridLayout();
198 layout.numColumns = 2;
199 g.setLayout(layout);
200 g.setText(text);
201 final GridData gd = new GridData();
202 gd.grabExcessHorizontalSpace = true;
203 gd.horizontalAlignment = SWT.FILL;
204 g.setLayoutData(gd);
205 return g;
208 private static void newLabel(final Group g, final String text) {
209 new Label(g, SWT.NULL).setText(text);
212 private static GridData createFieldGridData() {
213 return new GridData(SWT.FILL, SWT.DEFAULT, true, false);
217 * @return location the user wants to store this repository.
219 public File getDestinationFile() {
220 return new File(directoryText.getText());
224 * @return initial branch selected (includes refs/heads prefix).
226 public String getInitialBranch() {
227 final int ix = initialBranch.getSelectionIndex();
228 if (ix < 0)
229 return Constants.R_HEADS + Constants.MASTER;
230 return Constants.R_HEADS + initialBranch.getItem(ix);
234 * @return remote name
236 public String getRemote() {
237 return remoteText.getText();
241 * Check internal state for page completion status.
243 private void checkPage() {
244 final String dstpath = directoryText.getText();
245 if (dstpath.length() == 0) {
246 setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
247 UIText.CloneDestinationPage_promptDirectory));
248 setPageComplete(false);
249 return;
251 final File absoluteFile = new File(dstpath).getAbsoluteFile();
252 if (!absoluteFile.getAbsolutePath().equals(alreadyClonedInto)
253 && !isEmptyDir(absoluteFile)) {
254 setErrorMessage(NLS.bind(
255 UIText.CloneDestinationPage_errorNotEmptyDir, absoluteFile
256 .getPath()));
257 setPageComplete(false);
258 return;
261 if (!canCreateSubdir(absoluteFile.getParentFile())) {
262 setErrorMessage(NLS.bind(UIText.GitCloneWizard_errorCannotCreate,
263 absoluteFile.getPath()));
264 setPageComplete(false);
265 return;
267 if (!branchPage.isSourceRepoEmpty()
268 && initialBranch.getSelectionIndex() < 0) {
269 setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
270 UIText.CloneDestinationPage_promptInitialBranch));
271 setPageComplete(false);
272 return;
274 if (remoteText.getText().length() == 0) {
275 setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
276 UIText.CloneDestinationPage_promptRemoteName));
277 setPageComplete(false);
278 return;
281 setErrorMessage(null);
282 setPageComplete(true);
285 private static boolean isEmptyDir(final File dir) {
286 if (!dir.exists())
287 return true;
288 if (!dir.isDirectory())
289 return false;
290 return dir.listFiles().length == 0;
293 // this is actually just an optimistic heuristic - should be named
294 // isThereHopeThatCanCreateSubdir() as probably there is no 100% reliable
295 // way to check that in Java for Windows
296 private static boolean canCreateSubdir(final File parent) {
297 if (parent == null)
298 return true;
299 if (parent.exists())
300 return parent.isDirectory() && parent.canWrite();
301 return canCreateSubdir(parent.getParentFile());
304 private void revalidate() {
305 if (sourcePage.selectionEquals(validatedRepoSelection)
306 && branchPage.selectionEquals(validatedSelectedBranches,
307 validatedHEAD)) {
308 checkPage();
309 return;
312 if (!sourcePage.selectionEquals(validatedRepoSelection)) {
313 validatedRepoSelection = sourcePage.getSelection();
314 // update repo-related selection only if it changed
315 final String n = validatedRepoSelection.getURI().getHumanishName();
316 setDescription(NLS.bind(UIText.CloneDestinationPage_description, n));
317 directoryText.setText(new File(ResourcesPlugin.getWorkspace()
318 .getRoot().getRawLocation().toFile(), n).getAbsolutePath());
321 validatedSelectedBranches = branchPage.getSelectedBranches();
322 validatedHEAD = branchPage.getHEAD();
324 initialBranch.removeAll();
325 final Ref head = branchPage.getHEAD();
326 int newix = 0;
327 for (final Ref r : branchPage.getSelectedBranches()) {
328 String name = r.getName();
329 if (name.startsWith(Constants.R_HEADS))
330 name = name.substring((Constants.R_HEADS).length());
331 if (head != null && head.getName().equals(r.getName()))
332 newix = initialBranch.getItemCount();
333 initialBranch.add(name);
335 initialBranch.select(newix);
336 checkPage();
339 @Override
340 public boolean canFlipToNextPage() {
341 return super.canFlipToNextPage() && showImportWizard.getSelection();