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
;
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
;
84 private IFileRevision
[] fileRevisions
;
86 public GitHistoryPage(Object object
) {
90 public boolean inputSet() {
92 viewer
.setInput(getInput());
93 // TODO Auto-generated method stub
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(
115 final GitCompareRevisionAction compareActionPrev
= new GitCompareRevisionAction(
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(
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);
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
}));
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);
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
) {
187 public String
getColumnText(Object element
, int columnIndex
) {
188 if (columnIndex
== 0) {
189 int count
= ((GitFileRevision
) element
).getCount();
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
));
207 return patch
.getName();
211 if (id
.length() > 9) // make sure "Workspace" is spelled out
212 return id
.substring(0, 7) + "..";
216 return id
+ "@.." + rs
;
219 if (columnIndex
== 2)
222 if (columnIndex
== 3) {
223 Date d
= new Date(((IFileRevision
) element
).getTimestamp());
224 if (d
.getTime() == -1)
228 if (columnIndex
== 4)
229 return ((IFileRevision
) element
).getAuthor();
231 if (columnIndex
== 5) {
232 String comment
= ((IFileRevision
) element
).getComment();
235 int p
= comment
.indexOf('\n');
237 return comment
.substring(0, p
);
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
) {
256 TreeItem item
= (TreeItem
) event
.item
;
257 Tree parent
= item
.getParent();
258 if (parent
== null) {
259 item
.setText(new String
[] { "hej", "san" });
262 ITableLabelProvider p
= (ITableLabelProvider
) viewer
264 for (int i
= 0; i
< 6; ++i
) {
265 String text
= p
.getColumnText(
266 fileRevisions
[event
.index
], i
);
268 item
.setText(i
, text
);
272 item
.setData(fileRevisions
[event
.index
]);
274 } catch (Throwable b
) {
279 TableLayout layout
= new TableLayout();
280 tree
.setLayout(layout
);
282 viewer
= new TreeViewer(tree
, SWT
.VIRTUAL
| SWT
.FULL_SELECTION
);
284 viewer
.setUseHashlookup(true);
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)
303 System
.out
.println("inputChanged(" + viewer
+ "," + oldInput
+ ","
305 IProject project
= ((IResource
) getInput()).getProject();
306 RepositoryProvider provider
= RepositoryProvider
307 .getProvider(project
);
308 RepositoryMapping repositoryMapping
= ((GitProvider
)provider
).getData().getRepositoryMapping(project
);
310 appliedPatches
= null;
311 appliedPatches
= repositoryMapping
.getRepository().getAppliedPatches();
312 } catch (IOException e
) {
313 // TODO Auto-generated catch block
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();
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");
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
344 public Object
getParent(Object element
) {
345 // System.out.println("getParent(" + element + ")");
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);
367 TreeColumn col
= new TreeColumn(tree
, SWT
.NONE
);
368 col
.setResizable(true);
370 // X col.addSelectionListener(headerListener);
371 ((TableLayout
) tree
.getLayout()).addColumnData(new ColumnWeightData(15,
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,
383 col
= new TreeColumn(tree
, SWT
.NONE
);
384 col
.setResizable(true);
386 // X col.addSelectionListener(headerListener);
387 ((TableLayout
) tree
.getLayout()).addColumnData(new ColumnWeightData(15,
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,
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,
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,
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
435 public void refresh() {
436 // TODO Auto-generated method stub
440 public Object
getAdapter(Class adapter
) {
441 if (adapter
== IHistoryCompareAdapter
.class) {
447 public ICompareInput
getCompareInput(Object object
) {
448 // TODO Auto-generated method stub
452 public void prepareInput(ICompareInput input
,
453 CompareConfiguration configuration
, IProgressMonitor monitor
) {
454 System
.out
.println("prepareInput()");
455 // TODO Auto-generated method stub