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
;
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
;
87 private IFileRevision
[] fileRevisions
;
89 protected boolean hintShowDiffNow
;
91 public GitHistoryPage(Object object
) {
95 public boolean inputSet() {
97 viewer
.setInput(getInput());
98 // TODO Auto-generated method stub
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(
120 final GitCompareRevisionAction compareActionPrev
= new GitCompareRevisionAction(
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(
148 IProject project
= ((IResource
) getInput()).getProject();
149 GitProvider provider
= (GitProvider
)RepositoryProvider
150 .getProvider(project
);
151 RepositoryMapping repositoryMapping
= provider
.getData().getRepositoryMapping(project
);
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() {
166 if (GitCompareRevisionAction
.findReusableCompareEditor(GitHistoryPage
.this.getSite().getPage()) != null)
167 compareActionPrev
.run();
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);
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
) {
216 public String
getColumnText(Object element
, int columnIndex
) {
217 if (columnIndex
== 0) {
218 int count
= ((GitFileRevision
) element
).getCount();
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
));
236 return patch
.getName();
240 if (id
.length() > 9) // make sure "Workspace" is spelled out
241 return id
.substring(0, 7) + "..";
245 return id
+ "@.." + rs
;
248 if (columnIndex
== 2)
251 if (columnIndex
== 3) {
252 Date d
= new Date(((IFileRevision
) element
).getTimestamp());
253 if (d
.getTime() == -1)
257 if (columnIndex
== 4)
258 return ((IFileRevision
) element
).getAuthor();
260 if (columnIndex
== 5) {
261 String comment
= ((IFileRevision
) element
).getComment();
264 int p
= comment
.indexOf('\n');
266 return comment
.substring(0, p
);
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
) {
285 TreeItem item
= (TreeItem
) event
.item
;
286 Tree parent
= item
.getParent();
287 if (parent
== null) {
288 item
.setText(new String
[] { "hej", "san" });
291 ITableLabelProvider p
= (ITableLabelProvider
) viewer
293 for (int i
= 0; i
< 6; ++i
) {
294 String text
= p
.getColumnText(
295 fileRevisions
[event
.index
], i
);
297 item
.setText(i
, text
);
301 item
.setData(fileRevisions
[event
.index
]);
303 } catch (Throwable b
) {
308 TableLayout layout
= new TableLayout();
309 tree
.setLayout(layout
);
311 viewer
= new TreeViewer(tree
, SWT
.VIRTUAL
| SWT
.FULL_SELECTION
);
313 viewer
.setUseHashlookup(true);
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)
332 System
.out
.println("inputChanged(" + viewer
+ "," + oldInput
+ ","
334 IProject project
= ((IResource
) getInput()).getProject();
335 RepositoryProvider provider
= RepositoryProvider
336 .getProvider(project
);
337 RepositoryMapping repositoryMapping
= ((GitProvider
)provider
).getData().getRepositoryMapping(project
);
339 appliedPatches
= null;
340 appliedPatches
= repositoryMapping
.getRepository().getAppliedPatches();
341 } catch (IOException e
) {
342 // TODO Auto-generated catch block
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();
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");
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
373 public Object
getParent(Object element
) {
374 // System.out.println("getParent(" + element + ")");
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);
396 TreeColumn col
= new TreeColumn(tree
, SWT
.NONE
);
397 col
.setResizable(true);
399 // X col.addSelectionListener(headerListener);
400 ((TableLayout
) tree
.getLayout()).addColumnData(new ColumnWeightData(15,
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,
412 col
= new TreeColumn(tree
, SWT
.NONE
);
413 col
.setResizable(true);
415 // X col.addSelectionListener(headerListener);
416 ((TableLayout
) tree
.getLayout()).addColumnData(new ColumnWeightData(15,
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,
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,
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,
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
464 public void refresh() {
465 // TODO Auto-generated method stub
469 public Object
getAdapter(Class adapter
) {
470 if (adapter
== IHistoryCompareAdapter
.class) {
476 public ICompareInput
getCompareInput(Object object
) {
477 // TODO Auto-generated method stub
481 public void prepareInput(ICompareInput input
,
482 CompareConfiguration configuration
, IProgressMonitor monitor
) {
483 System
.out
.println("prepareInput()");
484 // TODO Auto-generated method stub