CommitDialog: Added context menu to add selected entries to index
[egit/egit-new.git] / org.spearce.egit.ui / src / org / spearce / egit / ui / internal / dialogs / CommitDialog.java
blob3cc0a4414dd9f039dc5de0f6c1aad72a92cb8fc9
1 /*
2 * Copyright (C) 2007 David Watson <dwatson@mimvista.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License, version 2.1, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18 package org.spearce.egit.ui.internal.dialogs;
20 import java.io.File;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
26 import org.eclipse.core.resources.IFile;
27 import org.eclipse.jface.dialogs.Dialog;
28 import org.eclipse.jface.dialogs.IDialogConstants;
29 import org.eclipse.jface.dialogs.MessageDialog;
30 import org.eclipse.jface.layout.GridDataFactory;
31 import org.eclipse.jface.viewers.CheckboxTableViewer;
32 import org.eclipse.jface.viewers.IStructuredContentProvider;
33 import org.eclipse.jface.viewers.IStructuredSelection;
34 import org.eclipse.jface.viewers.ITableLabelProvider;
35 import org.eclipse.jface.viewers.Viewer;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.events.SelectionListener;
39 import org.eclipse.swt.graphics.Image;
40 import org.eclipse.swt.layout.GridLayout;
41 import org.eclipse.swt.widgets.Button;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Control;
44 import org.eclipse.swt.widgets.Event;
45 import org.eclipse.swt.widgets.Label;
46 import org.eclipse.swt.widgets.Listener;
47 import org.eclipse.swt.widgets.Menu;
48 import org.eclipse.swt.widgets.MenuItem;
49 import org.eclipse.swt.widgets.Shell;
50 import org.eclipse.swt.widgets.Table;
51 import org.eclipse.swt.widgets.TableColumn;
52 import org.eclipse.swt.widgets.Text;
53 import org.eclipse.ui.model.WorkbenchLabelProvider;
54 import org.spearce.egit.core.project.GitProjectData;
55 import org.spearce.egit.core.project.RepositoryMapping;
56 import org.spearce.jgit.lib.GitIndex;
57 import org.spearce.jgit.lib.PersonIdent;
58 import org.spearce.jgit.lib.Repository;
59 import org.spearce.jgit.lib.Tree;
60 import org.spearce.jgit.lib.TreeEntry;
61 import org.spearce.jgit.lib.GitIndex.Entry;
63 /**
64 * @author dwatson Dialog is shown to user when they request to commit files.
65 * Changes in the selected portion of the tree are shown.
67 public class CommitDialog extends Dialog {
69 class CommitLabelProvider extends WorkbenchLabelProvider implements
70 ITableLabelProvider {
71 public String getColumnText(Object obj, int columnIndex) {
72 IFile file = (IFile) obj;
73 if (columnIndex == 1)
74 return file.getProject().getName() + ": "
75 + file.getProjectRelativePath();
77 else if (columnIndex == 0) {
78 String prefix = "Unknown";
80 final GitProjectData projectData = GitProjectData.get(file
81 .getProject());
82 try {
83 RepositoryMapping repositoryMapping = projectData
84 .getRepositoryMapping(file.getProject());
86 Repository repo = repositoryMapping.getRepository();
87 GitIndex index = repo.getIndex();
88 Tree headTree = repo.mapTree("HEAD");
90 String repoPath = repositoryMapping
91 .getRepoRelativePath(file);
92 TreeEntry headEntry = headTree.findBlobMember(repoPath);
93 boolean headExists = headTree.existsBlob(repoPath);
95 Entry indexEntry = index.getEntry(repoPath);
96 if (headEntry == null) {
97 prefix = "Added";
98 if (indexEntry.isModified(repositoryMapping.getWorkDir()))
99 prefix = "Added, index diff";
100 } else if (indexEntry == null) {
101 prefix = "Removed";
102 } else if (headExists
103 && !headEntry.getId().equals(
104 indexEntry.getObjectId())) {
105 prefix = "Modified";
108 if (indexEntry.isModified(repositoryMapping.getWorkDir()))
109 prefix = "Mod., index diff";
110 } else if (!new File(repositoryMapping.getWorkDir(), indexEntry.getName()).isFile()) {
111 prefix = "Rem., not staged";
112 } else if (indexEntry.isModified(repositoryMapping.getWorkDir())) {
113 prefix = "Mod., not staged";
116 } catch (Exception e) {
119 return prefix;
121 return null;
124 public Image getColumnImage(Object element, int columnIndex) {
125 if (columnIndex == 0)
126 return getImage(element);
127 return null;
131 ArrayList<IFile> files;
134 * @param parentShell
136 public CommitDialog(Shell parentShell) {
137 super(parentShell);
140 @Override
141 protected void createButtonsForButtonBar(Composite parent) {
142 createButton(parent, IDialogConstants.SELECT_ALL_ID, "Select All", false);
143 createButton(parent, IDialogConstants.DESELECT_ALL_ID, "Deselect All", false);
145 createButton(parent, IDialogConstants.OK_ID, "Commit", true);
146 createButton(parent, IDialogConstants.CANCEL_ID,
147 IDialogConstants.CANCEL_LABEL, true);
150 Text commitText;
151 Text authorText;
152 Button amendingButton;
153 Button signedOffButton;
155 CheckboxTableViewer filesViewer;
157 @Override
158 protected Control createDialogArea(Composite parent) {
159 Composite container = (Composite) super.createDialogArea(parent);
160 parent.getShell().setText("Commit Changes");
162 GridLayout layout = new GridLayout(2, false);
163 container.setLayout(layout);
165 Label label = new Label(container, SWT.LEFT);
166 label.setText("Commit Message:");
167 label.setLayoutData(GridDataFactory.fillDefaults().span(2, 1).create());
169 commitText = new Text(container, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
170 commitText.setLayoutData(GridDataFactory.fillDefaults().span(2, 1)
171 .hint(600, 200).create());
173 new Label(container, SWT.LEFT).setText("Author: ");
174 authorText = new Text(container, SWT.BORDER);
175 authorText.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
176 if (author != null)
177 authorText.setText(author);
179 amendingButton = new Button(container, SWT.CHECK);
180 if (amending) {
181 amendingButton.setSelection(amending);
182 amendingButton.setEnabled(false); // if already set, don't allow any changes
183 commitText.setText(previousCommitMessage);
185 amendingButton.addSelectionListener(new SelectionListener() {
186 boolean alreadyAdded = false;
187 public void widgetSelected(SelectionEvent arg0) {
188 if (alreadyAdded)
189 return;
190 if (amendingButton.getSelection()) {
191 alreadyAdded = true;
192 String curText = commitText.getText();
193 if (curText.length() > 0)
194 curText += "\n";
195 commitText.setText(curText + previousCommitMessage);
199 public void widgetDefaultSelected(SelectionEvent arg0) {
203 amendingButton.setText("Amend previous commit");
204 amendingButton.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(2, 1).create());
206 signedOffButton = new Button(container, SWT.CHECK);
207 signedOffButton.setSelection(signedOff);
208 signedOffButton.setText("Add Signed-off-by");
209 signedOffButton.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(2, 1).create());
211 Table resourcesTable = new Table(container, SWT.H_SCROLL | SWT.V_SCROLL
212 | SWT.FULL_SELECTION | SWT.MULTI | SWT.CHECK | SWT.BORDER);
213 resourcesTable.setLayoutData(GridDataFactory.fillDefaults().hint(600,
214 200).span(2,1).create());
216 resourcesTable.setHeaderVisible(true);
217 TableColumn statCol = new TableColumn(resourcesTable, SWT.LEFT);
218 statCol.setText("Status");
219 statCol.setWidth(150);
221 TableColumn resourceCol = new TableColumn(resourcesTable, SWT.LEFT);
222 resourceCol.setText("File");
223 resourceCol.setWidth(415);
225 filesViewer = new CheckboxTableViewer(resourcesTable);
226 filesViewer.setContentProvider(new IStructuredContentProvider() {
228 public void inputChanged(Viewer viewer, Object oldInput,
229 Object newInput) {
232 public void dispose() {
235 public Object[] getElements(Object inputElement) {
236 return files.toArray();
240 filesViewer.setLabelProvider(new CommitLabelProvider());
241 filesViewer.setInput(files);
242 filesViewer.setAllChecked(true);
243 filesViewer.getTable().setMenu(getContextMenu());
245 container.pack();
246 return container;
249 private Menu getContextMenu() {
250 Menu menu = new Menu(filesViewer.getTable());
251 MenuItem item = new MenuItem(menu, SWT.PUSH);
252 item.setText("Add file on disk to index");
253 item.addListener(SWT.Selection, new Listener() {
254 public void handleEvent(Event arg0) {
255 IStructuredSelection sel = (IStructuredSelection) filesViewer.getSelection();
256 if (sel.isEmpty()) {
257 return;
259 for (Iterator<Object> it = sel.iterator(); it.hasNext();) {
260 IFile file = (IFile) it.next();
262 final GitProjectData projectData = GitProjectData.get(file
263 .getProject());
264 RepositoryMapping repositoryMapping = projectData
265 .getRepositoryMapping(file.getProject());
267 Repository repo = repositoryMapping.getRepository();
268 GitIndex index = null;
269 try {
270 index = repo.getIndex();
271 Entry entry = index.getEntry(repositoryMapping.getRepoRelativePath(file));
272 if (entry != null && entry.isModified(repositoryMapping.getWorkDir())) {
273 entry.update(new File(repositoryMapping.getWorkDir(), entry.getName()), repo);
275 } catch (IOException e) {
276 e.printStackTrace();
277 return;
280 filesViewer.refresh(true);
284 return menu;
287 public String getCommitMessage() {
288 return commitMessage;
291 public void setCommitMessage(String s) {
292 this.commitMessage = s;
295 private String commitMessage = "";
296 private String author = null;
297 private boolean signedOff = false;
298 private boolean amending = false;
300 private ArrayList<IFile> selectedItems = new ArrayList<IFile>();
301 private String previousCommitMessage = "";
303 public void setSelectedItems(IFile[] items) {
304 Collections.addAll(selectedItems, items);
307 public IFile[] getSelectedItems() {
308 return selectedItems.toArray(new IFile[0]);
311 @Override
312 protected void okPressed() {
313 commitMessage = commitText.getText();
314 author = authorText.getText().trim();
315 signedOff = signedOffButton.getSelection();
316 amending = amendingButton.getSelection();
318 Object[] checkedElements = filesViewer.getCheckedElements();
319 selectedItems.clear();
320 for (Object obj : checkedElements)
321 selectedItems.add((IFile) obj);
323 if (commitMessage.trim().length() == 0) {
324 MessageDialog.openWarning(getShell(), "No message", "You must enter a commit message");
325 return;
328 if (author.length() > 0) {
329 try {
330 new PersonIdent(author);
331 } catch (IllegalArgumentException e) {
332 MessageDialog.openWarning(getShell(), "Invalid author", "Invalid author specified. Please use the form:\nA U Thor <author@example.com>");
333 return;
335 } else author = null;
337 if (selectedItems.isEmpty() && !amending) {
338 MessageDialog.openWarning(getShell(), "No items selected", "No items are currently selected to be committed.");
339 return;
341 super.okPressed();
344 public void setFileList(ArrayList<IFile> files) {
345 this.files = files;
348 @Override
349 protected void buttonPressed(int buttonId) {
350 if (IDialogConstants.SELECT_ALL_ID == buttonId) {
351 filesViewer.setAllChecked(true);
353 if (IDialogConstants.DESELECT_ALL_ID == buttonId) {
354 filesViewer.setAllChecked(false);
356 super.buttonPressed(buttonId);
359 public String getAuthor() {
360 return author;
363 public void setAuthor(String author) {
364 this.author = author;
367 public boolean isSignedOff() {
368 return signedOff;
371 public void setSignedOff(boolean signedOff) {
372 this.signedOff = signedOff;
375 public boolean isAmending() {
376 return amending;
379 public void setAmending(boolean amending) {
380 this.amending = amending;
383 public void setPreviousCommitMessage(String string) {
384 this.previousCommitMessage = string;