Recursion and update of all elements regardless of need.
[egit.git] / org.spearce.egit.ui / src / org / spearce / egit / ui / GitHistoryPage.java
blob8be23ec852dda3a9f074518d779c1a1fa56a1954
1 /*
2 * Copyright (C) 2006 Robin Rosenberg
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
17 package org.spearce.egit.ui;
19 import java.io.IOException;
20 import java.util.Date;
21 import java.util.Map;
23 import org.eclipse.compare.CompareConfiguration;
24 import org.eclipse.compare.structuremergeviewer.ICompareInput;
25 import org.eclipse.core.resources.IProject;
26 import org.eclipse.core.resources.IResource;
27 import org.eclipse.core.resources.IResourceChangeEvent;
28 import org.eclipse.core.resources.IResourceChangeListener;
29 import org.eclipse.core.resources.ResourcesPlugin;
30 import org.eclipse.core.runtime.IAdaptable;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.jface.action.IMenuListener;
33 import org.eclipse.jface.action.IMenuManager;
34 import org.eclipse.jface.action.MenuManager;
35 import org.eclipse.jface.viewers.ColumnWeightData;
36 import org.eclipse.jface.viewers.ILazyTreeContentProvider;
37 import org.eclipse.jface.viewers.ITableLabelProvider;
38 import org.eclipse.jface.viewers.ITreeContentProvider;
39 import org.eclipse.jface.viewers.LabelProvider;
40 import org.eclipse.jface.viewers.StructuredSelection;
41 import org.eclipse.jface.viewers.TableLayout;
42 import org.eclipse.jface.viewers.TreeViewer;
43 import org.eclipse.jface.viewers.Viewer;
44 import org.eclipse.swt.SWT;
45 import org.eclipse.swt.events.SelectionAdapter;
46 import org.eclipse.swt.events.SelectionEvent;
47 import org.eclipse.swt.graphics.Image;
48 import org.eclipse.swt.layout.GridData;
49 import org.eclipse.swt.layout.GridLayout;
50 import org.eclipse.swt.widgets.Composite;
51 import org.eclipse.swt.widgets.Control;
52 import org.eclipse.swt.widgets.Event;
53 import org.eclipse.swt.widgets.Listener;
54 import org.eclipse.swt.widgets.Menu;
55 import org.eclipse.swt.widgets.Tree;
56 import org.eclipse.swt.widgets.TreeColumn;
57 import org.eclipse.swt.widgets.TreeItem;
58 import org.eclipse.team.core.RepositoryProvider;
59 import org.eclipse.team.core.history.IFileHistory;
60 import org.eclipse.team.core.history.IFileHistoryProvider;
61 import org.eclipse.team.core.history.IFileRevision;
62 import org.eclipse.team.internal.ui.TeamUIMessages;
63 import org.eclipse.team.internal.ui.history.DialogHistoryPageSite;
64 import org.eclipse.team.ui.history.HistoryPage;
65 import org.eclipse.team.ui.history.IHistoryCompareAdapter;
66 import org.eclipse.team.ui.history.IHistoryPageSite;
67 import org.spearce.egit.core.GitProvider;
68 import org.spearce.egit.core.internal.mapping.GitFileRevision;
69 import org.spearce.egit.core.project.RepositoryMapping;
70 import org.spearce.egit.ui.internal.actions.GitCompareRevisionAction;
71 import org.spearce.jgit.lib.Commit;
72 import org.spearce.jgit.lib.ObjectId;
73 import org.spearce.jgit.lib.Repository.StGitPatch;
75 public class GitHistoryPage extends HistoryPage implements IAdaptable,
76 IHistoryCompareAdapter {
78 private Composite localComposite;
80 private TreeViewer viewer;
82 private Tree tree;
84 private IFileRevision[] fileRevisions;
86 public GitHistoryPage(Object object) {
87 setInput(object);
90 public boolean inputSet() {
91 if (viewer != null)
92 viewer.setInput(getInput());
93 // TODO Auto-generated method stub
94 return true;
97 public void createControl(Composite parent) {
98 localComposite = new Composite(parent, SWT.NONE);
99 GridLayout layout = new GridLayout();
100 layout.marginHeight = 0;
101 layout.marginWidth = 0;
102 localComposite.setLayout(layout);
103 GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
104 data.grabExcessVerticalSpace = true;
105 localComposite.setLayoutData(data);
107 createTree(localComposite);
109 IHistoryPageSite parentSite = getHistoryPageSite();
110 if (parentSite != null && parentSite instanceof DialogHistoryPageSite)
111 parentSite.setSelectionProvider(viewer);
113 final GitCompareRevisionAction compareAction = new GitCompareRevisionAction(
114 "Compare");
115 final GitCompareRevisionAction compareActionPrev = new GitCompareRevisionAction(
116 "Show commit");
117 tree.addSelectionListener(new SelectionAdapter() {
118 public void widgetSelected(SelectionEvent e) {
119 // update the current
120 TreeItem[] selection = tree.getSelection();
121 IFileRevision[] selection2 = new IFileRevision[selection.length];
122 for (int i = 0; i < selection.length; ++i) {
123 selection2[i] = (IFileRevision) selection[i].getData();
126 compareAction.setCurrentFileRevision(fileRevisions[0]);
127 compareAction.selectionChanged(new StructuredSelection(
128 selection2));
129 IProject project = ((IResource) getInput()).getProject();
130 GitProvider provider = (GitProvider)RepositoryProvider
131 .getProvider(project);
132 RepositoryMapping repositoryMapping = provider.getData().getRepositoryMapping(project);
133 ObjectId parentId = (ObjectId)((GitFileRevision)selection2[0]).getCommit().getParentIds().get(0);
134 try {
135 if (selection2.length == 1) {
136 Commit parent = repositoryMapping.getRepository().mapCommit(parentId);
137 IFileRevision previous = new GitFileRevision(parent,
138 ((GitFileRevision)selection2[0]).getResource(),
139 ((GitFileRevision)selection2[0]).getCount()+1);
140 // compareActionPrev.setCurrentFileRevision(selection2[0]);
141 compareActionPrev.setCurrentFileRevision(null);
142 compareActionPrev.selectionChanged(new StructuredSelection(new IFileRevision[] {selection2[0], previous}));
143 } else {
144 compareActionPrev.setCurrentFileRevision(null);
145 compareActionPrev.selectionChanged(new StructuredSelection(new IFileRevision[0]));
147 } catch (IOException e1) {
148 // TODO Auto-generated catch block
149 e1.printStackTrace();
153 compareAction.setPage(this);
154 compareActionPrev.setPage(this);
155 MenuManager menuMgr = new MenuManager();
156 Menu menu = menuMgr.createContextMenu(tree);
157 menuMgr.addMenuListener(new IMenuListener() {
158 public void menuAboutToShow(IMenuManager menuMgr) {
159 menuMgr.add(compareAction);
160 menuMgr.add(compareActionPrev);
163 menuMgr.setRemoveAllWhenShown(true);
164 tree.setMenu(menu);
166 GitHistoryResourceListener resourceListener = new GitHistoryResourceListener();
167 ResourcesPlugin.getWorkspace().addResourceChangeListener(
168 resourceListener, IResourceChangeEvent.POST_CHANGE);
172 class GitHistoryResourceListener implements IResourceChangeListener {
174 public void resourceChanged(IResourceChangeEvent event) {
175 System.out.println("resourceChanged(" + event + ")");
180 class GitHistoryLabelProvider extends LabelProvider implements
181 ITableLabelProvider {
183 public Image getColumnImage(Object element, int columnIndex) {
184 return null;
187 public String getColumnText(Object element, int columnIndex) {
188 if (columnIndex == 0) {
189 int count = ((GitFileRevision) element).getCount();
190 if (count < 0)
191 return "";
192 else
193 if (count == 0)
194 return "HEAD";
195 else
196 return "HEAD~"+count;
199 if (columnIndex == 1) {
200 String rss = ((IFileRevision) element).getURI().toString();
201 String rs = rss.substring(rss.length()-10);
202 String id = ((IFileRevision) element).getContentIdentifier();
203 if (appliedPatches!=null) {
204 if (!id.equals("Workspace")) {
205 StGitPatch patch = (StGitPatch) appliedPatches.get(new ObjectId(id));
206 if (patch!=null)
207 return patch.getName();
210 if (id != null)
211 if (id.length() > 9) // make sure "Workspace" is spelled out
212 return id.substring(0, 7) + "..";
213 else
214 return id;
215 else
216 return id + "@.." + rs;
219 if (columnIndex == 2)
220 return ""; // TAGS
222 if (columnIndex == 3) {
223 Date d = new Date(((IFileRevision) element).getTimestamp());
224 if (d.getTime() == -1)
225 return "";
226 return d.toString();
228 if (columnIndex == 4)
229 return ((IFileRevision) element).getAuthor();
231 if (columnIndex == 5) {
232 String comment = ((IFileRevision) element).getComment();
233 if (comment == null)
234 return null;
235 int p = comment.indexOf('\n');
236 if (p >= 0)
237 return comment.substring(0, p);
238 else
239 return comment;
241 return Integer.toString(columnIndex);
245 private void createTree(Composite composite) {
246 tree = new Tree(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI
247 | SWT.FULL_SELECTION | SWT.VIRTUAL);
248 tree.setHeaderVisible(true);
249 tree.setLinesVisible(true);
250 GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
251 tree.setLayoutData(data);
252 tree.setData("HEAD");
253 tree.addListener(SWT.SetData, new Listener() {
254 public void handleEvent(Event event) {
255 try {
256 TreeItem item = (TreeItem) event.item;
257 Tree parent = item.getParent();
258 if (parent == null) {
259 item.setText(new String[] { "hej", "san" });
260 item.setData("");
261 } else {
262 ITableLabelProvider p = (ITableLabelProvider) viewer
263 .getLabelProvider();
264 for (int i = 0; i < 6; ++i) {
265 String text = p.getColumnText(
266 fileRevisions[event.index], i);
267 if (text != null)
268 item.setText(i, text);
269 else
270 item.setText(i, "");
272 item.setData(fileRevisions[event.index]);
274 } catch (Throwable b) {
275 b.printStackTrace();
279 TableLayout layout = new TableLayout();
280 tree.setLayout(layout);
282 viewer = new TreeViewer(tree, SWT.VIRTUAL | SWT.FULL_SELECTION);
284 viewer.setUseHashlookup(true);
286 createColumns();
288 viewer.setLabelProvider(new GitHistoryLabelProvider());
290 viewer.setContentProvider(new GitHistoryContentProvider());
292 viewer.setInput(getInput());
295 private Map appliedPatches;
297 class GitHistoryContentProvider implements ITreeContentProvider,
298 ILazyTreeContentProvider {
300 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
301 if (newInput == null)
302 return;
303 System.out.println("inputChanged(" + viewer + "," + oldInput + ","
304 + newInput);
305 IProject project = ((IResource) getInput()).getProject();
306 RepositoryProvider provider = RepositoryProvider
307 .getProvider(project);
308 RepositoryMapping repositoryMapping = ((GitProvider)provider).getData().getRepositoryMapping(project);
309 try {
310 appliedPatches = null;
311 appliedPatches = repositoryMapping.getRepository().getAppliedPatches();
312 } catch (IOException e) {
313 // TODO Auto-generated catch block
314 e.printStackTrace();
316 IFileHistoryProvider fileHistoryProvider = provider
317 .getFileHistoryProvider();
318 IFileHistory fileHistoryFor = fileHistoryProvider
319 .getFileHistoryFor((IResource) getInput(),
320 IFileHistoryProvider.SINGLE_LINE_OF_DESCENT, null/* monitor */);
321 fileRevisions = fileHistoryFor.getFileRevisions();
322 tree.removeAll();
323 tree.setItemCount(fileRevisions.length);
324 tree.setData(fileRevisions);
325 tree.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));
326 System.out.println("inputchanged, invoking refresh");
327 viewer.refresh();
330 public void dispose() {
331 // TODO Auto-generated method stub
334 public Object[] getElements(Object inputElement) {
335 System.out.println("getElements(" + inputElement + ")");
336 return fileRevisions;
339 public boolean hasChildren(Object element) {
340 // TODO Auto-generated method stub
341 return false;
344 public Object getParent(Object element) {
345 // System.out.println("getParent(" + element + ")");
346 return null;
349 public Object[] getChildren(Object parentElement) {
350 // System.out.println("getElements(" + parentElement + ")");
351 return fileRevisions;
354 public void updateChildCount(Object element, int currentChildCount) {
355 viewer.setChildCount(element, fileRevisions.length);
358 public void updateElement(Object parent, int index) {
359 System.out.println("updateElement("+parent+","+index);
360 viewer.replace(parent, index, fileRevisions[index]);
364 private void createColumns() {
365 // X SelectionListener headerListener = getColumnListener(viewer);
366 // count from head
367 TreeColumn col = new TreeColumn(tree, SWT.NONE);
368 col.setResizable(true);
369 col.setText("^");
370 // X col.addSelectionListener(headerListener);
371 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(15,
372 true));
374 // revision
375 col = new TreeColumn(tree, SWT.NONE);
376 col.setResizable(true);
377 col.setText(TeamUIMessages.GenericHistoryTableProvider_Revision);
378 // X col.addSelectionListener(headerListener);
379 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(15,
380 true));
382 // tags
383 col = new TreeColumn(tree, SWT.NONE);
384 col.setResizable(true);
385 col.setText("Tags");
386 // X col.addSelectionListener(headerListener);
387 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(15,
388 true));
389 // creation date
390 col = new TreeColumn(tree, SWT.NONE);
391 col.setResizable(true);
392 col.setText(TeamUIMessages.GenericHistoryTableProvider_RevisionTime);
393 // X col.addSelectionListener(headerListener);
394 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(30,
395 true));
397 // author
398 col = new TreeColumn(tree, SWT.NONE);
399 col.setResizable(true);
400 col.setText(TeamUIMessages.GenericHistoryTableProvider_Author);
401 // X col.addSelectionListener(headerListener);
402 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(20,
403 true));
405 // comment
406 col = new TreeColumn(tree, SWT.NONE);
407 col.setResizable(true);
408 col.setText(TeamUIMessages.GenericHistoryTableProvider_Comment);
409 // X col.addSelectionListener(headerListener);
410 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(35,
411 true));
414 public Control getControl() {
415 return localComposite;
418 public void setFocus() {
419 localComposite.setFocus();
422 public String getDescription() {
423 return "GIT History viewer";
426 public String getName() {
427 return getInput().toString();
430 public boolean isValidInput(Object object) {
431 // TODO Auto-generated method stub
432 return true;
435 public void refresh() {
436 // TODO Auto-generated method stub
440 public Object getAdapter(Class adapter) {
441 if (adapter == IHistoryCompareAdapter.class) {
442 return this;
444 return null;
447 public ICompareInput getCompareInput(Object object) {
448 // TODO Auto-generated method stub
449 return null;
452 public void prepareInput(ICompareInput input,
453 CompareConfiguration configuration, IProgressMonitor monitor) {
454 System.out.println("prepareInput()");
455 // TODO Auto-generated method stub