Update compare window immediately
[egit.git] / org.spearce.egit.ui / src / org / spearce / egit / ui / GitHistoryPage.java
blob4b437a66d7d79b4d41f9d1aa6b19bc9ba01ab2df
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.List;
22 import java.util.Map;
24 import org.eclipse.compare.CompareConfiguration;
25 import org.eclipse.compare.structuremergeviewer.ICompareInput;
26 import org.eclipse.core.resources.IProject;
27 import org.eclipse.core.resources.IResource;
28 import org.eclipse.core.resources.IResourceChangeEvent;
29 import org.eclipse.core.resources.IResourceChangeListener;
30 import org.eclipse.core.resources.ResourcesPlugin;
31 import org.eclipse.core.runtime.IAdaptable;
32 import org.eclipse.core.runtime.IProgressMonitor;
33 import org.eclipse.jface.action.IMenuListener;
34 import org.eclipse.jface.action.IMenuManager;
35 import org.eclipse.jface.action.MenuManager;
36 import org.eclipse.jface.viewers.ColumnWeightData;
37 import org.eclipse.jface.viewers.ILazyTreeContentProvider;
38 import org.eclipse.jface.viewers.ITableLabelProvider;
39 import org.eclipse.jface.viewers.ITreeContentProvider;
40 import org.eclipse.jface.viewers.LabelProvider;
41 import org.eclipse.jface.viewers.StructuredSelection;
42 import org.eclipse.jface.viewers.TableLayout;
43 import org.eclipse.jface.viewers.TreeViewer;
44 import org.eclipse.jface.viewers.Viewer;
45 import org.eclipse.swt.SWT;
46 import org.eclipse.swt.events.MouseEvent;
47 import org.eclipse.swt.events.MouseListener;
48 import org.eclipse.swt.events.SelectionAdapter;
49 import org.eclipse.swt.events.SelectionEvent;
50 import org.eclipse.swt.graphics.Image;
51 import org.eclipse.swt.layout.GridData;
52 import org.eclipse.swt.layout.GridLayout;
53 import org.eclipse.swt.widgets.Composite;
54 import org.eclipse.swt.widgets.Control;
55 import org.eclipse.swt.widgets.Event;
56 import org.eclipse.swt.widgets.Listener;
57 import org.eclipse.swt.widgets.Menu;
58 import org.eclipse.swt.widgets.Tree;
59 import org.eclipse.swt.widgets.TreeColumn;
60 import org.eclipse.swt.widgets.TreeItem;
61 import org.eclipse.team.core.RepositoryProvider;
62 import org.eclipse.team.core.history.IFileHistory;
63 import org.eclipse.team.core.history.IFileHistoryProvider;
64 import org.eclipse.team.core.history.IFileRevision;
65 import org.eclipse.team.internal.ui.TeamUIMessages;
66 import org.eclipse.team.internal.ui.history.DialogHistoryPageSite;
67 import org.eclipse.team.ui.history.HistoryPage;
68 import org.eclipse.team.ui.history.IHistoryCompareAdapter;
69 import org.eclipse.team.ui.history.IHistoryPageSite;
70 import org.spearce.egit.core.GitProvider;
71 import org.spearce.egit.core.internal.mapping.GitFileRevision;
72 import org.spearce.egit.core.project.RepositoryMapping;
73 import org.spearce.egit.ui.internal.actions.GitCompareRevisionAction;
74 import org.spearce.jgit.lib.Commit;
75 import org.spearce.jgit.lib.ObjectId;
76 import org.spearce.jgit.lib.Repository.StGitPatch;
78 public class GitHistoryPage extends HistoryPage implements IAdaptable,
79 IHistoryCompareAdapter {
81 private Composite localComposite;
83 private TreeViewer viewer;
85 private Tree tree;
87 private IFileRevision[] fileRevisions;
89 protected boolean hintShowDiffNow;
91 public GitHistoryPage(Object object) {
92 setInput(object);
95 public boolean inputSet() {
96 if (viewer != null)
97 viewer.setInput(getInput());
98 // TODO Auto-generated method stub
99 return true;
102 public void createControl(Composite parent) {
103 localComposite = new Composite(parent, SWT.NONE);
104 GridLayout layout = new GridLayout();
105 layout.marginHeight = 0;
106 layout.marginWidth = 0;
107 localComposite.setLayout(layout);
108 GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
109 data.grabExcessVerticalSpace = true;
110 localComposite.setLayoutData(data);
112 createTree(localComposite);
114 IHistoryPageSite parentSite = getHistoryPageSite();
115 if (parentSite != null && parentSite instanceof DialogHistoryPageSite)
116 parentSite.setSelectionProvider(viewer);
118 final GitCompareRevisionAction compareAction = new GitCompareRevisionAction(
119 "Compare");
120 final GitCompareRevisionAction compareActionPrev = new GitCompareRevisionAction(
121 "Show commit");
122 tree.addMouseListener(new MouseListener() {
124 public void mouseUp(MouseEvent e) {
127 public void mouseDown(MouseEvent e) {
128 hintShowDiffNow = e.button==1;
131 public void mouseDoubleClick(MouseEvent e) {
136 tree.addSelectionListener(new SelectionAdapter() {
137 public void widgetSelected(SelectionEvent e) {
138 // update the current
139 TreeItem[] selection = tree.getSelection();
140 IFileRevision[] selection2 = new IFileRevision[selection.length];
141 for (int i = 0; i < selection.length; ++i) {
142 selection2[i] = (IFileRevision) selection[i].getData();
145 compareAction.setCurrentFileRevision(fileRevisions[0]);
146 compareAction.selectionChanged(new StructuredSelection(
147 selection2));
148 IProject project = ((IResource) getInput()).getProject();
149 GitProvider provider = (GitProvider)RepositoryProvider
150 .getProvider(project);
151 RepositoryMapping repositoryMapping = provider.getData().getRepositoryMapping(project);
152 try {
153 if (selection2.length == 1 && hintShowDiffNow) {
154 List parentIds = ((GitFileRevision)selection2[0]).getCommit().getParentIds();
155 if (parentIds.size() > 0) {
156 ObjectId parentId = (ObjectId)parentIds.get(0);
157 Commit parent = repositoryMapping.getRepository().mapCommit(parentId);
158 IFileRevision previous = new GitFileRevision(parent,
159 ((GitFileRevision)selection2[0]).getResource(),
160 ((GitFileRevision)selection2[0]).getCount()+1);
161 compareActionPrev.setCurrentFileRevision(null);
162 compareActionPrev.selectionChanged(new StructuredSelection(new IFileRevision[] {selection2[0], previous}));
163 System.out.println("detail="+e.detail);
164 tree.getDisplay().asyncExec(new Runnable() {
165 public void run() {
166 if (GitCompareRevisionAction.findReusableCompareEditor(GitHistoryPage.this.getSite().getPage()) != null)
167 compareActionPrev.run();
171 } else {
172 compareActionPrev.setCurrentFileRevision(null);
173 compareActionPrev.selectionChanged(new StructuredSelection(new IFileRevision[0]));
175 } catch (IOException e1) {
176 // TODO Auto-generated catch block
177 e1.printStackTrace();
179 hintShowDiffNow = false;
182 compareAction.setPage(this);
183 compareActionPrev.setPage(this);
184 MenuManager menuMgr = new MenuManager();
185 Menu menu = menuMgr.createContextMenu(tree);
186 menuMgr.addMenuListener(new IMenuListener() {
187 public void menuAboutToShow(IMenuManager menuMgr) {
188 menuMgr.add(compareAction);
189 menuMgr.add(compareActionPrev);
192 menuMgr.setRemoveAllWhenShown(true);
193 tree.setMenu(menu);
195 GitHistoryResourceListener resourceListener = new GitHistoryResourceListener();
196 ResourcesPlugin.getWorkspace().addResourceChangeListener(
197 resourceListener, IResourceChangeEvent.POST_CHANGE);
201 class GitHistoryResourceListener implements IResourceChangeListener {
203 public void resourceChanged(IResourceChangeEvent event) {
204 System.out.println("resourceChanged(" + event + ")");
209 class GitHistoryLabelProvider extends LabelProvider implements
210 ITableLabelProvider {
212 public Image getColumnImage(Object element, int columnIndex) {
213 return null;
216 public String getColumnText(Object element, int columnIndex) {
217 if (columnIndex == 0) {
218 int count = ((GitFileRevision) element).getCount();
219 if (count < 0)
220 return "";
221 else
222 if (count == 0)
223 return "HEAD";
224 else
225 return "HEAD~"+count;
228 if (columnIndex == 1) {
229 String rss = ((IFileRevision) element).getURI().toString();
230 String rs = rss.substring(rss.length()-10);
231 String id = ((IFileRevision) element).getContentIdentifier();
232 if (appliedPatches!=null) {
233 if (!id.equals("Workspace")) {
234 StGitPatch patch = (StGitPatch) appliedPatches.get(new ObjectId(id));
235 if (patch!=null)
236 return patch.getName();
239 if (id != null)
240 if (id.length() > 9) // make sure "Workspace" is spelled out
241 return id.substring(0, 7) + "..";
242 else
243 return id;
244 else
245 return id + "@.." + rs;
248 if (columnIndex == 2)
249 return ""; // TAGS
251 if (columnIndex == 3) {
252 Date d = new Date(((IFileRevision) element).getTimestamp());
253 if (d.getTime() == -1)
254 return "";
255 return d.toString();
257 if (columnIndex == 4)
258 return ((IFileRevision) element).getAuthor();
260 if (columnIndex == 5) {
261 String comment = ((IFileRevision) element).getComment();
262 if (comment == null)
263 return null;
264 int p = comment.indexOf('\n');
265 if (p >= 0)
266 return comment.substring(0, p);
267 else
268 return comment;
270 return Integer.toString(columnIndex);
274 private void createTree(Composite composite) {
275 tree = new Tree(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI
276 | SWT.FULL_SELECTION | SWT.VIRTUAL);
277 tree.setHeaderVisible(true);
278 tree.setLinesVisible(true);
279 GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
280 tree.setLayoutData(data);
281 tree.setData("HEAD");
282 tree.addListener(SWT.SetData, new Listener() {
283 public void handleEvent(Event event) {
284 try {
285 TreeItem item = (TreeItem) event.item;
286 Tree parent = item.getParent();
287 if (parent == null) {
288 item.setText(new String[] { "hej", "san" });
289 item.setData("");
290 } else {
291 ITableLabelProvider p = (ITableLabelProvider) viewer
292 .getLabelProvider();
293 for (int i = 0; i < 6; ++i) {
294 String text = p.getColumnText(
295 fileRevisions[event.index], i);
296 if (text != null)
297 item.setText(i, text);
298 else
299 item.setText(i, "");
301 item.setData(fileRevisions[event.index]);
303 } catch (Throwable b) {
304 b.printStackTrace();
308 TableLayout layout = new TableLayout();
309 tree.setLayout(layout);
311 viewer = new TreeViewer(tree, SWT.VIRTUAL | SWT.FULL_SELECTION);
313 viewer.setUseHashlookup(true);
315 createColumns();
317 viewer.setLabelProvider(new GitHistoryLabelProvider());
319 viewer.setContentProvider(new GitHistoryContentProvider());
321 viewer.setInput(getInput());
324 private Map appliedPatches;
326 class GitHistoryContentProvider implements ITreeContentProvider,
327 ILazyTreeContentProvider {
329 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
330 if (newInput == null)
331 return;
332 System.out.println("inputChanged(" + viewer + "," + oldInput + ","
333 + newInput);
334 IProject project = ((IResource) getInput()).getProject();
335 RepositoryProvider provider = RepositoryProvider
336 .getProvider(project);
337 RepositoryMapping repositoryMapping = ((GitProvider)provider).getData().getRepositoryMapping(project);
338 try {
339 appliedPatches = null;
340 appliedPatches = repositoryMapping.getRepository().getAppliedPatches();
341 } catch (IOException e) {
342 // TODO Auto-generated catch block
343 e.printStackTrace();
345 IFileHistoryProvider fileHistoryProvider = provider
346 .getFileHistoryProvider();
347 IFileHistory fileHistoryFor = fileHistoryProvider
348 .getFileHistoryFor((IResource) getInput(),
349 IFileHistoryProvider.SINGLE_LINE_OF_DESCENT, null/* monitor */);
350 fileRevisions = fileHistoryFor.getFileRevisions();
351 tree.removeAll();
352 tree.setItemCount(fileRevisions.length);
353 tree.setData(fileRevisions);
354 tree.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));
355 System.out.println("inputchanged, invoking refresh");
356 viewer.refresh();
359 public void dispose() {
360 // TODO Auto-generated method stub
363 public Object[] getElements(Object inputElement) {
364 System.out.println("getElements(" + inputElement + ")");
365 return fileRevisions;
368 public boolean hasChildren(Object element) {
369 // TODO Auto-generated method stub
370 return false;
373 public Object getParent(Object element) {
374 // System.out.println("getParent(" + element + ")");
375 return null;
378 public Object[] getChildren(Object parentElement) {
379 // System.out.println("getElements(" + parentElement + ")");
380 return fileRevisions;
383 public void updateChildCount(Object element, int currentChildCount) {
384 viewer.setChildCount(element, fileRevisions.length);
387 public void updateElement(Object parent, int index) {
388 System.out.println("updateElement("+parent+","+index);
389 viewer.replace(parent, index, fileRevisions[index]);
393 private void createColumns() {
394 // X SelectionListener headerListener = getColumnListener(viewer);
395 // count from head
396 TreeColumn col = new TreeColumn(tree, SWT.NONE);
397 col.setResizable(true);
398 col.setText("^");
399 // X col.addSelectionListener(headerListener);
400 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(15,
401 true));
403 // revision
404 col = new TreeColumn(tree, SWT.NONE);
405 col.setResizable(true);
406 col.setText(TeamUIMessages.GenericHistoryTableProvider_Revision);
407 // X col.addSelectionListener(headerListener);
408 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(15,
409 true));
411 // tags
412 col = new TreeColumn(tree, SWT.NONE);
413 col.setResizable(true);
414 col.setText("Tags");
415 // X col.addSelectionListener(headerListener);
416 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(15,
417 true));
418 // creation date
419 col = new TreeColumn(tree, SWT.NONE);
420 col.setResizable(true);
421 col.setText(TeamUIMessages.GenericHistoryTableProvider_RevisionTime);
422 // X col.addSelectionListener(headerListener);
423 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(30,
424 true));
426 // author
427 col = new TreeColumn(tree, SWT.NONE);
428 col.setResizable(true);
429 col.setText(TeamUIMessages.GenericHistoryTableProvider_Author);
430 // X col.addSelectionListener(headerListener);
431 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(20,
432 true));
434 // comment
435 col = new TreeColumn(tree, SWT.NONE);
436 col.setResizable(true);
437 col.setText(TeamUIMessages.GenericHistoryTableProvider_Comment);
438 // X col.addSelectionListener(headerListener);
439 ((TableLayout) tree.getLayout()).addColumnData(new ColumnWeightData(35,
440 true));
443 public Control getControl() {
444 return localComposite;
447 public void setFocus() {
448 localComposite.setFocus();
451 public String getDescription() {
452 return "GIT History viewer";
455 public String getName() {
456 return getInput().toString();
459 public boolean isValidInput(Object object) {
460 // TODO Auto-generated method stub
461 return true;
464 public void refresh() {
465 // TODO Auto-generated method stub
469 public Object getAdapter(Class adapter) {
470 if (adapter == IHistoryCompareAdapter.class) {
471 return this;
473 return null;
476 public ICompareInput getCompareInput(Object object) {
477 // TODO Auto-generated method stub
478 return null;
481 public void prepareInput(ICompareInput input,
482 CompareConfiguration configuration, IProgressMonitor monitor) {
483 System.out.println("prepareInput()");
484 // TODO Auto-generated method stub