View | Details | Raw Unified | Return to bug 143354 | Differences between
and this patch

Collapse All | Expand All

(-)C:/dev/eclipse/org.tigris.subversion.subclipse.ui/plugin.xml (+10 lines)
Lines 1006-1009 Link Here
1006
      </consolePatternMatchListener>
1006
      </consolePatternMatchListener>
1007
   </extension>	  
1007
   </extension>	  
1008
1008
1009
   <!-- history support -->
1010
   <extension
1011
         point="org.eclipse.core.runtime.adapters">
1012
			<factory
1013
            adaptableType="org.tigris.subversion.subclipse.core.SVNTeamProvider"
1014
            class="org.tigris.subversion.subclipse.ui.repository.model.SVNAdapterFactory">
1015
         <adapter type="org.eclipse.team.ui.history.IHistoryPageSource"/>
1016
      </factory>
1017
   </extension>
1018
1009
</plugin>
1019
</plugin>
(-)C:/dev/eclipse/org.tigris.subversion.subclipse.ui/src/org/tigris/subversion/subclipse/ui/history/SVNHistoryPage.java (+879 lines)
Line 0 Link Here
1
package org.tigris.subversion.subclipse.ui.history;
2
3
import java.util.ArrayList;
4
import java.util.HashSet;
5
import java.util.Iterator;
6
import java.util.Set;
7
import java.util.TreeMap;
8
9
import org.eclipse.core.resources.IResource;
10
import org.eclipse.core.runtime.IProgressMonitor;
11
import org.eclipse.core.runtime.IStatus;
12
import org.eclipse.core.runtime.Status;
13
import org.eclipse.core.runtime.jobs.Job;
14
import org.eclipse.jface.action.Action;
15
import org.eclipse.jface.action.IAction;
16
import org.eclipse.jface.preference.IPreferenceStore;
17
import org.eclipse.jface.resource.JFaceColors;
18
import org.eclipse.jface.text.Document;
19
import org.eclipse.jface.text.TextViewer;
20
import org.eclipse.jface.viewers.ISelection;
21
import org.eclipse.jface.viewers.ISelectionChangedListener;
22
import org.eclipse.jface.viewers.IStructuredContentProvider;
23
import org.eclipse.jface.viewers.IStructuredSelection;
24
import org.eclipse.jface.viewers.ITreeContentProvider;
25
import org.eclipse.jface.viewers.SelectionChangedEvent;
26
import org.eclipse.jface.viewers.StructuredSelection;
27
import org.eclipse.jface.viewers.StructuredViewer;
28
import org.eclipse.jface.viewers.TableViewer;
29
import org.eclipse.jface.viewers.Viewer;
30
import org.eclipse.swt.SWT;
31
import org.eclipse.swt.custom.SashForm;
32
import org.eclipse.swt.custom.StyleRange;
33
import org.eclipse.swt.custom.StyledText;
34
import org.eclipse.swt.graphics.Font;
35
import org.eclipse.swt.layout.GridData;
36
import org.eclipse.swt.widgets.Composite;
37
import org.eclipse.swt.widgets.Control;
38
import org.eclipse.swt.widgets.Display;
39
import org.eclipse.team.core.RepositoryProvider;
40
import org.eclipse.team.core.TeamException;
41
import org.eclipse.team.ui.history.HistoryPage;
42
import org.eclipse.ui.PlatformUI;
43
import org.tigris.subversion.subclipse.core.ISVNLocalResource;
44
import org.tigris.subversion.subclipse.core.ISVNRemoteResource;
45
import org.tigris.subversion.subclipse.core.SVNException;
46
import org.tigris.subversion.subclipse.core.SVNProviderPlugin;
47
import org.tigris.subversion.subclipse.core.SVNTeamProvider;
48
import org.tigris.subversion.subclipse.core.history.AliasManager;
49
import org.tigris.subversion.subclipse.core.history.ILogEntry;
50
import org.tigris.subversion.subclipse.core.history.LogEntry;
51
import org.tigris.subversion.subclipse.core.history.LogEntryChangePath;
52
import org.tigris.subversion.subclipse.core.resources.SVNWorkspaceRoot;
53
import org.tigris.subversion.subclipse.ui.ISVNUIConstants;
54
import org.tigris.subversion.subclipse.ui.Policy;
55
import org.tigris.subversion.subclipse.ui.SVNUIPlugin;
56
import org.tigris.subversion.subclipse.ui.internal.Utils;
57
import org.tigris.subversion.subclipse.ui.settings.ProjectProperties;
58
import org.tigris.subversion.subclipse.ui.util.LinkList;
59
import org.tigris.subversion.svnclientadapter.SVNRevision;
60
61
public class SVNHistoryPage extends HistoryPage {
62
63
  private SashForm svnHistoryPageControl;
64
  private SashForm innerSashForm;
65
  
66
  HistoryTableProvider historyTableProvider;
67
  TableViewer tableHistoryViewer;
68
  StructuredViewer changePathsViewer;
69
  TextViewer textViewer;
70
71
  private boolean showComments;
72
  private boolean showAffectedPaths;
73
  private boolean wrapCommentsText;
74
  boolean shutdown = false;
75
  
76
  private ProjectProperties projectProperties;
77
  private LinkList linkList;
78
  
79
  // cached for efficiency
80
  ILogEntry[] entries;
81
  LogEntryChangePath[] currentLogEntryChangePath;
82
  ILogEntry lastEntry;
83
  SVNRevision revisionStart = SVNRevision.HEAD;
84
  
85
  FetchLogEntriesJob fetchLogEntriesJob = null;
86
  FetchAllLogEntriesJob fetchAllLogEntriesJob = null;
87
  FetchNextLogEntriesJob fetchNextLogEntriesJob = null;
88
  FetchChangePathJob fetchChangePathJob = null;
89
  AliasManager tagManager;
90
  
91
  public IResource resource;
92
  
93
  IAction getNextAction;
94
  IAction toggleStopOnCopyAction;
95
  
96
  
97
  public SVNHistoryPage(Object object) {
98
    // TODO Auto-generated constructor stub
99
  }
100
101
  public Control getControl() {
102
    return svnHistoryPageControl;
103
  }
104
105
  public void setFocus() {
106
    // TODO Auto-generated method stub
107
108
  }
109
110
  public String getDescription() {
111
    // TODO Auto-generated method stub
112
    return null;
113
  }
114
115
  public String getName() {
116
    // TODO Auto-generated method stub
117
    return null;
118
  }
119
120
  public boolean isValidInput(Object object) {
121
    if(object instanceof IResource) {
122
      RepositoryProvider provider = RepositoryProvider.getProvider(((IResource) object).getProject());
123
      return provider instanceof SVNTeamProvider;
124
    } else if(object instanceof ISVNRemoteResource) {
125
      return true;
126
      // } else if(object instanceof CVSFileRevision) {
127
      // return true;
128
      // } else if(object instanceof CVSLocalFileRevision) {
129
      // return true;
130
    }
131
132
    // TODO
133
134
    return false;
135
  }
136
137
  public void refresh() {
138
    // TODO Auto-generated method stub
139
140
  }
141
142
  public Object getAdapter(Class adapter) {
143
    // TODO Auto-generated method stub
144
    return null;
145
  }
146
147
  public boolean inputSet() {
148
    Object input = getInput();
149
    if(!(input instanceof IResource)) {
150
      return false;
151
    }
152
    
153
    IResource res = (IResource) input;
154
    RepositoryProvider teamProvider = RepositoryProvider.getProvider(res.getProject(), SVNProviderPlugin.getTypeId());
155
    if (teamProvider != null) {
156
        try {
157
            ISVNLocalResource localResource = SVNWorkspaceRoot.getSVNResourceFor(res);
158
            if ( localResource != null
159
                    && !localResource.getStatus().isAdded()
160
                    && localResource.getStatus().isManaged() ) {
161
                projectProperties = ProjectProperties.getProjectProperties(res);
162
                ISVNRemoteResource baseResource = localResource.getBaseResource();
163
                historyTableProvider.setRemoteResource(baseResource);
164
                historyTableProvider.setResource(res);
165
                this.resource = res;
166
                tableHistoryViewer.setInput(baseResource);
167
                // setContentDescription(Policy.bind("HistoryView.titleWithArgument", baseResource.getName())); //$NON-NLS-1$
168
                // setTitleToolTip(baseResource.getRepositoryRelativePath());
169
                return true;
170
            }
171
        } catch (TeamException e) {
172
            SVNUIPlugin.openError(getSite().getShell(), null, null, e);
173
        }               
174
    }    
175
    // TODO
176
    return false;
177
  }
178
  
179
  public void createControl(Composite parent) {
180
    IPreferenceStore store = SVNUIPlugin.getPlugin().getPreferenceStore();
181
    // linkingEnabled = store.getBoolean(ISVNUIConstants.PREF_HISTORY_VIEW_EDITOR_LINKING);
182
183
    svnHistoryPageControl = new SashForm(parent, SWT.VERTICAL);
184
    svnHistoryPageControl.setLayoutData(new GridData(GridData.FILL_BOTH));
185
186
    createTableHistory(svnHistoryPageControl);
187
    createAffectedPathsViewer(store.getInt(ISVNUIConstants.PREF_AFFECTED_PATHS_LAYOUT));
188
    
189
    contributeActions();
190
191
    svnHistoryPageControl.setWeights(new int[] { 70, 30});
192
193
    // set F1 help
194
    // PlatformUI.getWorkbench().getHelpSystem().setHelp(svnHistoryPageControl, IHelpContextIds.RESOURCE_HISTORY_VIEW);
195
    // initDragAndDrop();
196
197
    // add listener for editor page activation - this is to support editor linking
198
    // getSite().getPage().addPartListener(partListener);
199
    // getSite().getPage().addPartListener(partListener2);
200
  }
201
202
  private void contributeActions() {
203
    SVNUIPlugin plugin = SVNUIPlugin.getPlugin();
204
    IPreferenceStore store = plugin.getPreferenceStore();
205
    
206
    // Toggle stop on copy action
207
    toggleStopOnCopyAction = new Action(Policy.bind("HistoryView.stopOnCopy")) { //$NON-NLS-1$
208
        public void run() {
209
            setStopOnCopy();
210
            SVNUIPlugin.getPlugin().getPreferenceStore().setValue(ISVNUIConstants.PREF_STOP_ON_COPY, toggleStopOnCopyAction.isChecked());
211
        }
212
    };
213
    toggleStopOnCopyAction.setChecked(store.getBoolean(ISVNUIConstants.PREF_STOP_ON_COPY));
214
215
    int entriesToFetch = store.getInt(ISVNUIConstants.PREF_LOG_ENTRIES_TO_FETCH);
216
    getNextAction = new Action(Policy.bind("HistoryView.getNext"), plugin.getImageDescriptor(ISVNUIConstants.IMG_GET_NEXT)) { //$NON-NLS-1$
217
        public void run() {
218
            final ISVNRemoteResource remoteResource = historyTableProvider.getRemoteResource();
219
            if(fetchNextLogEntriesJob == null) {
220
                fetchNextLogEntriesJob = new FetchNextLogEntriesJob();
221
            }
222
            if(fetchNextLogEntriesJob.getState() != Job.NONE) {
223
                fetchNextLogEntriesJob.cancel();
224
                try {
225
                    fetchNextLogEntriesJob.join();
226
                } catch (InterruptedException e) {
227
                    SVNUIPlugin.log(new SVNException(Policy.bind("HistoryView.errorFetchingEntries", remoteResource.getName()), e)); //$NON-NLS-1$
228
                }
229
            }
230
            fetchNextLogEntriesJob.setRemoteFile(remoteResource);
231
            Utils.schedule(fetchNextLogEntriesJob, getSite());
232
        }
233
    };
234
    getNextAction.setToolTipText(Policy.bind("HistoryView.getNext") + " " + entriesToFetch); //$NON-NLS-1$
235
    if (entriesToFetch <= 0) getNextAction.setEnabled(false);
236
  }
237
238
  void setStopOnCopy() {
239
      refresh();
240
  }
241
242
    protected void createTableHistory(Composite parent) {
243
    historyTableProvider = new HistoryTableProvider();
244
    tableHistoryViewer = historyTableProvider.createTable(parent);
245
246
    // set the content provider for the table
247
    tableHistoryViewer.setContentProvider(new IStructuredContentProvider() {
248
249
      public Object[] getElements(Object inputElement) {
250
        // Short-circuit to optimize
251
        if(entries != null)
252
          return entries;
253
254
        if( !(inputElement instanceof ISVNRemoteResource))
255
          return null;
256
        final ISVNRemoteResource remoteResource = (ISVNRemoteResource) inputElement;
257
258
        if(fetchLogEntriesJob == null) {
259
          fetchLogEntriesJob = new FetchLogEntriesJob();
260
        }
261
        if(fetchLogEntriesJob.getState() != Job.NONE) {
262
          fetchLogEntriesJob.cancel();
263
          try {
264
            fetchLogEntriesJob.join();
265
          } catch(InterruptedException e) {
266
            SVNUIPlugin.log(new SVNException(
267
                Policy.bind("HistoryView.errorFetchingEntries", remoteResource.getName()), e)); //$NON-NLS-1$
268
          }
269
        }
270
        fetchLogEntriesJob.setRemoteFile(remoteResource);
271
        Utils.schedule(fetchLogEntriesJob, SVNUIPlugin.getPlugin().getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart().getSite());
272
        
273
        return new Object[ 0];
274
      }
275
276
      public void dispose() {
277
      }
278
279
      public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
280
        entries = null;
281
        lastEntry = null;
282
        revisionStart = SVNRevision.HEAD;
283
      }
284
    });
285
286
    // set the selectionchanged listener for the table
287
    // updates the comments and affected paths when selection changes
288
    tableHistoryViewer.addSelectionChangedListener(new ISelectionChangedListener() {
289
      private ILogEntry currentLogEntry;
290
291
      public void selectionChanged(SelectionChangedEvent event) {
292
        ISelection selection = event.getSelection();
293
        ILogEntry logEntry = getLogEntry((IStructuredSelection) selection);
294
        if(logEntry != currentLogEntry) {
295
          this.currentLogEntry = logEntry;
296
          updatePanels(selection);
297
        }
298
      }
299
    });
300
301
  }
302
303
  public void createAffectedPathsViewer(int layout) {
304
//    for( int i = 0; i < toggleAffectedPathsLayoutActions.length; i++) {
305
//      ToggleAffectedPathsLayoutAction action = toggleAffectedPathsLayoutActions[i];
306
//      action.setChecked(layout==action.getLayout());
307
//    }
308
    
309
    if(innerSashForm!=null) {
310
      innerSashForm.dispose();
311
    }
312
    if(changePathsViewer!=null) {
313
      changePathsViewer.getControl().dispose();
314
    }
315
    
316
    innerSashForm = new SashForm(svnHistoryPageControl, SWT.HORIZONTAL);
317
318
    switch(layout) {
319
      case ISVNUIConstants.LAYOUT_COMPRESSED:
320
        changePathsViewer = new ChangePathsTreeViewer(innerSashForm);
321
        changePathsViewer.setContentProvider(new ChangePathsTreeContentProvider());
322
        break;
323
      default:
324
        changePathsViewer = new ChangePathsTableProvider(innerSashForm);
325
        changePathsViewer.setContentProvider(new ChangePathsTableContentProvider());
326
        break;
327
    }
328
    
329
//    changePathsViewer.addSelectionChangedListener(new ISelectionChangedListener() {
330
//        public void selectionChanged(SelectionChangedEvent event) {
331
//            selection = changePathsViewer.getSelection();
332
//        }         
333
//    });
334
    
335
//    changePathsViewer.getControl().addListener(SWT.DefaultSelection, new Listener() {
336
//          public void handleEvent(Event e) {
337
//              getOpenChangedPathAction().run();
338
//          }
339
//      });
340
    
341
    textViewer = createText(innerSashForm);
342
    setViewerVisibility();
343
    innerSashForm.layout();
344
    svnHistoryPageControl.layout();
345
    
346
    updatePanels(tableHistoryViewer.getSelection());
347
  }
348
  
349
  /**
350
   * Create the TextViewer for the logEntry comments 
351
   */
352
    protected TextViewer createText(Composite parent) {
353
        TextViewer result = new TextViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.READ_ONLY);
354
//        result.addSelectionChangedListener(new ISelectionChangedListener() {
355
//            public void selectionChanged(SelectionChangedEvent event) {
356
//                copyAction.update();
357
//            }
358
//        });
359
      
360
      Font font = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getFontRegistry().get(ISVNUIConstants.SVN_COMMENT_FONT);
361
      if (font != null) result.getTextWidget().setFont(font);
362
//      result.getTextWidget().addMouseListener(new MouseAdapter() {
363
//          public void mouseDown(MouseEvent e) {
364
//              if (e.button != 1) {
365
//                  return;
366
//              }
367
//              mouseDown = true;
368
//          }
369
//          public void mouseUp(MouseEvent e) {
370
//              mouseDown = false;
371
//              StyledText text = (StyledText)e.widget;
372
//              int offset = text.getCaretOffset();
373
//              if (dragEvent) {
374
//                  // don't activate a link during a drag/mouse up operation
375
//                  dragEvent = false;
376
//                  if (linkList != null && linkList.isLinkAt(offset)) {
377
//                      text.setCursor(handCursor);
378
//                  }
379
//              } else {
380
//                  if (linkList != null && linkList.isLinkAt(offset)) {    
381
//                      text.setCursor(busyCursor);
382
//                      openLink(linkList.getLinkAt(offset));
383
//                      text.setCursor(null);
384
//                  }
385
//              }
386
//          }           
387
//      });
388
      
389
//      result.getTextWidget().addMouseMoveListener(new MouseMoveListener() {
390
//          public void mouseMove(MouseEvent e) {
391
//              // Do not change cursor on drag events
392
//              if (mouseDown) {
393
//                  if (!dragEvent) {
394
//                      StyledText text = (StyledText)e.widget;
395
//                      text.setCursor(null);
396
//                  }
397
//                  dragEvent = true;
398
//                  return;
399
//              }
400
//              StyledText text = (StyledText)e.widget;
401
//              int offset = -1;
402
//              try {
403
//                  offset = text.getOffsetAtLocation(new Point(e.x, e.y));
404
//              } catch (IllegalArgumentException ex) {}
405
//              if (offset == -1)
406
//                  text.setCursor(null);
407
//              else if (linkList != null && linkList.isLinkAt(offset)) 
408
//                  text.setCursor(handCursor);
409
//              else 
410
//                  text.setCursor(null);                
411
//          }           
412
//      });
413
      
414
      // Create actions for the text editor (copy and select all)
415
//      copyAction = new TextViewerAction(result, ITextOperationTarget.COPY);
416
//      copyAction.setText(Policy.bind("HistoryView.copy")); //$NON-NLS-1$
417
//      
418
//      selectAllAction = new TextViewerAction(result, ITextOperationTarget.SELECT_ALL);
419
//      selectAllAction.setText(Policy.bind("HistoryView.selectAll")); //$NON-NLS-1$
420
//
421
//      getHistoryPageSite().getToolBarManager().
422
//      
423
//      IActionBars actionBars = getViewSite().getActionBars();
424
//      actionBars.setGlobalActionHandler(ITextEditorActionConstants.COPY, copyAction);
425
//      actionBars.setGlobalActionHandler(ITextEditorActionConstants.SELECT_ALL, selectAllAction);
426
//      actionBars.updateActionBars();
427
//
428
//      // Contribute actions to popup menu for the comments area
429
//      {
430
//           MenuManager menuMgr = new MenuManager();
431
//           menuMgr.setRemoveAllWhenShown(true);
432
//           menuMgr.addMenuListener(new IMenuListener() {
433
//                   public void menuAboutToShow(IMenuManager menuMgr) {
434
//                           fillTextMenu(menuMgr);
435
//                   }
436
//           });
437
//  
438
//           StyledText text = result.getTextWidget();
439
//           Menu menu = menuMgr.createContextMenu(text);
440
//           text.setMenu(menu);
441
//      }
442
      
443
      
444
        return result;
445
    }
446
447
    ILogEntry getLogEntry(IStructuredSelection ss) {
448
      if(ss.getFirstElement() instanceof LogEntryChangePath) {
449
        return ((LogEntryChangePath)ss.getFirstElement()).getLogEntry();
450
      }
451
      return (ILogEntry) ss.getFirstElement();
452
    }
453
    
454
    void updatePanels(ISelection selection) {
455
      if (selection == null || !(selection instanceof IStructuredSelection)) {
456
        textViewer.setDocument(new Document("")); //$NON-NLS-1$
457
        changePathsViewer.setInput(null);
458
        return;
459
      }
460
      IStructuredSelection ss = (IStructuredSelection)selection;
461
      if (ss.size() != 1) {
462
        textViewer.setDocument(new Document("")); //$NON-NLS-1$
463
        changePathsViewer.setInput(null);
464
        return;
465
      }
466
      LogEntry entry = (LogEntry)ss.getFirstElement();
467
      textViewer.setDocument(new Document(entry.getComment()));
468
      StyledText text = textViewer.getTextWidget();
469
      if (projectProperties == null) linkList = ProjectProperties.getUrls(entry.getComment());
470
      else linkList = projectProperties.getLinkList(entry.getComment());
471
      if (linkList != null) {
472
        int[][] linkRanges = linkList.getLinkRanges();
473
        // String[] urls = linkList.getUrls();
474
        for (int i = 0; i < linkRanges.length; i++) {
475
            text.setStyleRange(new StyleRange(linkRanges[i][0], linkRanges[i][1], JFaceColors.getHyperlinkText(Display.getCurrent()), null));                      
476
        }
477
      }
478
      changePathsViewer.setInput(entry);
479
    }
480
481
    void setViewerVisibility() {
482
      if (showComments && showAffectedPaths) {
483
          svnHistoryPageControl.setMaximizedControl(null);
484
          innerSashForm.setMaximizedControl(null);
485
      } else if (showComments) {
486
          svnHistoryPageControl.setMaximizedControl(null);
487
          innerSashForm.setMaximizedControl(textViewer.getTextWidget());
488
      } else if (showAffectedPaths) {
489
          svnHistoryPageControl.setMaximizedControl(null);
490
          innerSashForm.setMaximizedControl(changePathsViewer.getControl());
491
      } else {
492
          svnHistoryPageControl.setMaximizedControl(tableHistoryViewer.getControl());
493
      }
494
    
495
      changePathsViewer.refresh();
496
      textViewer.getTextWidget().setWordWrap(wrapCommentsText);
497
   }
498
  
499
   void setCurrentLogEntryChangePath( final LogEntryChangePath[] currentLogEntryChangePath) {
500
      this.currentLogEntryChangePath = currentLogEntryChangePath;
501
      if(!shutdown) {
502
          //Getting the changePaths
503
          /*
504
          final SVNRevision.Number revisionId = remoteResource.getLastChangedRevision();
505
          */
506
          getSite().getShell().getDisplay().asyncExec(new Runnable() {
507
                  public void run() {
508
                      if(currentLogEntryChangePath != null && changePathsViewer != null && !changePathsViewer.getControl().isDisposed()) {
509
                          // once we got the changePath, we refresh the table 
510
                          changePathsViewer.refresh();
511
                          //selectRevision(revisionId);
512
                      }
513
                  }
514
              });
515
      }
516
  }
517
  
518
    /**
519
     * Select the revision in the receiver.
520
     */
521
    public void selectRevision(SVNRevision.Number revision) {
522
        if (entries == null) {
523
            return;
524
        }
525
    
526
        ILogEntry entry = null;
527
        for (int i = 0; i < entries.length; i++) {
528
            if (entries[i].getRevision().equals(revision)) {
529
                entry = entries[i];
530
                break;
531
            }
532
        }
533
    
534
        if (entry != null) {
535
            IStructuredSelection selection = new StructuredSelection(entry);
536
            tableHistoryViewer.setSelection(selection, true);
537
        }
538
    }
539
540
    public void scheduleFetchChangePathJob(ILogEntry logEntry) {
541
      if(fetchChangePathJob == null) {
542
          fetchChangePathJob = new FetchChangePathJob();
543
      }
544
      if(fetchChangePathJob.getState() != Job.NONE) {
545
          fetchChangePathJob.cancel();
546
          try {
547
              fetchChangePathJob.join();
548
          } catch (InterruptedException e) {
549
              e.printStackTrace();
550
              //SVNUIPlugin.log(new SVNException(Policy.bind("HistoryView.errorFetchingEntries", remoteResource.getName()), e)); //$NON-NLS-1$
551
          }
552
      }
553
      fetchChangePathJob.setLogEntry(logEntry);
554
      Utils.schedule(fetchChangePathJob, getSite());
555
  }
556
  
557
  public boolean isShowChangePaths() {
558
      // return toggleShowAffectedPathsAction.isChecked();
559
    return true;
560
  }
561
  
562
    
563
    
564
    
565
    private class FetchLogEntriesJob extends Job {
566
        public ISVNRemoteResource remoteResource;
567
        public FetchLogEntriesJob() {
568
            super(Policy.bind("HistoryView.fetchHistoryJob"));  //$NON-NLS-1$;
569
        }
570
        public void setRemoteFile(ISVNRemoteResource resource) {
571
            this.remoteResource = resource;
572
        }
573
        public IStatus run(IProgressMonitor monitor) {
574
            try {
575
                if(remoteResource != null && !shutdown) {
576
                    if (resource == null) {
577
                        if (remoteResource == null || !SVNUIPlugin.getPlugin().getPreferenceStore().getBoolean(ISVNUIConstants.PREF_SHOW_TAGS_IN_REMOTE))
578
                            tagManager = null;
579
                        else
580
                            tagManager = new AliasManager(remoteResource.getUrl());
581
                    }
582
                    else tagManager = new AliasManager(resource);
583
                    SVNRevision pegRevision = remoteResource.getRevision();
584
                    SVNRevision revisionEnd = new SVNRevision.Number(0);
585
                    boolean stopOnCopy = toggleStopOnCopyAction.isChecked();
586
                    IPreferenceStore store = SVNUIPlugin.getPlugin().getPreferenceStore();
587
                    int entriesToFetch = store.getInt(ISVNUIConstants.PREF_LOG_ENTRIES_TO_FETCH);
588
                    long limit = entriesToFetch;
589
                    entries = remoteResource.getLogEntries(monitor, pegRevision, revisionStart, revisionEnd, stopOnCopy, limit + 1, tagManager);
590
                    long entriesLength = entries.length;
591
                    if (entriesLength > limit) {
592
                      ILogEntry[] fetchedEntries = new ILogEntry[entries.length - 1];
593
                      for (int i = 0; i < entries.length - 1; i++)
594
                          fetchedEntries[i] = entries[i];
595
                      entries = fetchedEntries;
596
                      getNextAction.setEnabled(true);
597
                    } else {
598
                      getNextAction.setEnabled(false);
599
                    }
600
                    final SVNRevision.Number revisionId = remoteResource.getLastChangedRevision();
601
                    getSite().getShell().getDisplay().asyncExec(new Runnable() {
602
                        public void run() {
603
                            if(entries != null && tableHistoryViewer != null && ! tableHistoryViewer.getTable().isDisposed()) {
604
                              // once we got the entries, we refresh the table 
605
                                if (entries.length > 0) {
606
                                    lastEntry = entries[entries.length - 1];
607
                                    long lastEntryNumber = lastEntry.getRevision().getNumber();
608
                                    revisionStart = new SVNRevision.Number(lastEntryNumber - 1);
609
                                }                               
610
                              tableHistoryViewer.refresh();
611
                                selectRevision(revisionId);
612
                            }
613
                        }
614
                    });
615
                }
616
                return Status.OK_STATUS;
617
            } catch (TeamException e) {
618
                return e.getStatus();
619
            }
620
        }
621
    }
622
    
623
    private class FetchNextLogEntriesJob extends Job {
624
        public ISVNRemoteResource remoteResource;
625
        public FetchNextLogEntriesJob() {
626
            super(Policy.bind("HistoryView.fetchHistoryJob"));  //$NON-NLS-1$;
627
        }
628
        public void setRemoteFile(ISVNRemoteResource resource) {
629
            this.remoteResource = resource;
630
        }
631
        public IStatus run(IProgressMonitor monitor) {
632
            try {
633
                if(remoteResource != null && !shutdown) {
634
                    SVNRevision pegRevision = remoteResource.getRevision();
635
                    SVNRevision revisionEnd = new SVNRevision.Number(0);
636
                    boolean stopOnCopy = toggleStopOnCopyAction.isChecked();
637
                    IPreferenceStore store = SVNUIPlugin.getPlugin().getPreferenceStore();
638
                    int entriesToFetch = store.getInt(ISVNUIConstants.PREF_LOG_ENTRIES_TO_FETCH);
639
                    long limit = entriesToFetch;
640
                    ILogEntry[] nextEntries = remoteResource.getLogEntries(monitor, pegRevision, revisionStart, revisionEnd, stopOnCopy, limit + 1, tagManager);
641
                    long entriesLength = nextEntries.length;
642
                    if (entriesLength > limit) {
643
                        ILogEntry[] fetchedEntries = new ILogEntry[nextEntries.length - 1];
644
                        for (int i = 0; i < nextEntries.length - 1; i++)
645
                            fetchedEntries[i] = nextEntries[i];
646
                        getNextAction.setEnabled(true);
647
                    } else {
648
                      getNextAction.setEnabled(false);
649
                    }
650
                    ArrayList entryArray = new ArrayList();
651
                    if (entries == null) entries = new ILogEntry[0];
652
                    for (int i = 0; i < entries.length; i++) entryArray.add(entries[i]);
653
                    for (int i = 0; i < nextEntries.length; i++) entryArray.add(nextEntries[i]);
654
                    entries = new ILogEntry[entryArray.size()];
655
                    entryArray.toArray(entries);
656
                    getSite().getShell().getDisplay().asyncExec(new Runnable() {
657
                        public void run() {
658
                            if(entries != null && tableHistoryViewer != null && ! tableHistoryViewer.getTable().isDisposed()) {
659
                              // once we got the entries, we refresh the table 
660
                                ISelection selection = tableHistoryViewer.getSelection();
661
                              tableHistoryViewer.refresh();
662
                              tableHistoryViewer.setSelection(selection);
663
                                if (entries.length > 0) {
664
                                    lastEntry = entries[entries.length - 1];
665
                                    long lastEntryNumber = lastEntry.getRevision().getNumber();
666
                                    revisionStart = new SVNRevision.Number(lastEntryNumber - 1);
667
                                }
668
                            }
669
                        }
670
                    });
671
                }
672
                return Status.OK_STATUS;
673
            } catch (TeamException e) {
674
                return e.getStatus();
675
            }
676
        }
677
    }
678
    
679
    private class FetchAllLogEntriesJob extends Job {
680
        public ISVNRemoteResource remoteResource;
681
        public FetchAllLogEntriesJob() {
682
            super(Policy.bind("HistoryView.fetchHistoryJob"));  //$NON-NLS-1$;
683
        }
684
        public void setRemoteFile(ISVNRemoteResource resource) {
685
            this.remoteResource = resource;
686
        }
687
        public IStatus run(IProgressMonitor monitor) {
688
            try {
689
                if(remoteResource != null && !shutdown) {
690
                    if (resource == null) {
691
                        if (remoteResource == null || !SVNUIPlugin.getPlugin().getPreferenceStore().getBoolean(ISVNUIConstants.PREF_SHOW_TAGS_IN_REMOTE))
692
                            tagManager = null;
693
                        else
694
                            tagManager = new AliasManager(remoteResource.getUrl());
695
                    }
696
                    else tagManager = new AliasManager(resource);
697
                    SVNRevision pegRevision = remoteResource.getRevision();
698
                    revisionStart = SVNRevision.HEAD;
699
                    SVNRevision revisionEnd = new SVNRevision.Number(0);
700
                    boolean stopOnCopy = toggleStopOnCopyAction.isChecked();
701
                    long limit = 0;
702
                    entries = remoteResource.getLogEntries(monitor, pegRevision, revisionStart, revisionEnd, stopOnCopy, limit, tagManager);
703
                    final SVNRevision.Number revisionId = remoteResource.getLastChangedRevision();
704
                    getSite().getShell().getDisplay().asyncExec(new Runnable() {
705
                        public void run() {
706
                            if(entries != null && tableHistoryViewer != null && ! tableHistoryViewer.getTable().isDisposed()) {
707
                              // once we got the entries, we refresh the table 
708
                              if (entries.length > 0) {
709
                                  lastEntry = entries[entries.length - 1];
710
                                  long lastEntryNumber = lastEntry.getRevision().getNumber();
711
                                  revisionStart = new SVNRevision.Number(lastEntryNumber - 1);
712
                              }                                       
713
                              tableHistoryViewer.refresh();
714
                              selectRevision(revisionId);
715
                            }
716
                        }
717
                    });
718
                }
719
                return Status.OK_STATUS;
720
            } catch (TeamException e) {
721
                return e.getStatus();
722
            }
723
        }
724
    }
725
    
726
    class FetchChangePathJob extends Job {
727
      public ILogEntry logEntry;
728
        
729
      public FetchChangePathJob() {
730
          super(Policy.bind("HistoryView.fetchChangePathJob"));  //$NON-NLS-1$;
731
        }
732
        
733
        public void setLogEntry(ILogEntry logEntry) {
734
            this.logEntry = logEntry;
735
        }        
736
        
737
        public IStatus run(IProgressMonitor monitor) {
738
            if(logEntry.getResource()!=null) {
739
                setCurrentLogEntryChangePath(logEntry.getLogEntryChangePaths());
740
          }
741
          return Status.OK_STATUS;    
742
        }
743
    }
744
745
  
746
    static final LogEntryChangePath[] EMPTY_CHANGE_PATHS = new LogEntryChangePath[0];
747
    class ChangePathsTableContentProvider implements IStructuredContentProvider {
748
749
      public Object[] getElements(Object inputElement) {
750
          if (!isShowChangePaths() || !(inputElement instanceof ILogEntry)) {
751
              return EMPTY_CHANGE_PATHS;
752
          }
753
        
754
        ILogEntry logEntry = (ILogEntry)inputElement;
755
          if (SVNProviderPlugin.getPlugin().getSVNClientManager().isFetchChangePathOnDemand()) {
756
              if (currentLogEntryChangePath != null) {
757
                  return currentLogEntryChangePath;
758
              }
759
              scheduleFetchChangePathJob(logEntry);
760
              return EMPTY_CHANGE_PATHS;
761
          }
762
763
          return logEntry.getLogEntryChangePaths();
764
      }
765
766
      public void dispose() {
767
      }
768
769
      public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
770
        currentLogEntryChangePath = null;
771
      }
772
      
773
  }
774
775
    class ChangePathsTreeContentProvider implements ITreeContentProvider {
776
777
      public Object[] getChildren(Object parentElement) {
778
          if(parentElement instanceof HistoryFolder) {
779
            return ((HistoryFolder) parentElement).getChildren();
780
          }
781
          return null;
782
      }
783
784
      public Object getParent(Object element) {
785
          return null;
786
      }
787
788
      public boolean hasChildren(Object element) {
789
          if(element instanceof HistoryFolder) {
790
              HistoryFolder folder = (HistoryFolder) element;
791
              return folder.getChildren().length>0;
792
          }
793
          return false;
794
      }
795
796
      public Object[] getElements(Object inputElement) {
797
          if (!isShowChangePaths() || !(inputElement instanceof ILogEntry)) {
798
              return EMPTY_CHANGE_PATHS;
799
          }
800
801
          if (currentLogEntryChangePath != null) {
802
              
803
          }
804
          
805
          ILogEntry logEntry = (ILogEntry)inputElement;
806
          if (SVNProviderPlugin.getPlugin().getSVNClientManager().isFetchChangePathOnDemand()) {
807
              if (currentLogEntryChangePath != null) {
808
                  return getGroups(currentLogEntryChangePath);
809
              }
810
              scheduleFetchChangePathJob(logEntry);
811
              return EMPTY_CHANGE_PATHS;
812
          }
813
814
          return getGroups(logEntry.getLogEntryChangePaths());
815
      }
816
      
817
      private Object[] getGroups(LogEntryChangePath[] changePaths) {
818
          // 1st pass. Collect folder names
819
          Set folderNames = new HashSet(); 
820
          for( int i = 0; i < changePaths.length; i++) {
821
            folderNames.add(getFolderName(changePaths[i]));
822
          }
823
          
824
          // 2nd pass. Sorting out explicitly changed folders
825
          TreeMap folders = new TreeMap();
826
          for( int i = 0; i < changePaths.length; i++) {
827
            LogEntryChangePath changePath = changePaths[i];
828
          String path = changePath.getPath();
829
            if(folderNames.contains(path)) {
830
              // changed folder
831
              HistoryFolder folder = (HistoryFolder) folders.get(path);
832
              if(folder==null) {
833
                folder = new HistoryFolder(changePath);
834
                folders.put(path, folder);
835
              }
836
            } else {
837
              // changed resource
838
              path = getFolderName(changePath);
839
              HistoryFolder folder = (HistoryFolder) folders.get(path);
840
              if(folder==null) {
841
                folder = new HistoryFolder(path);
842
                folders.put(path, folder);
843
              }
844
              folder.add(changePath);
845
            }
846
          }
847
          
848
          // 3rd pass. Optimize folders with one or no children 
849
          ArrayList groups = new ArrayList();
850
          for( Iterator it = folders.values().iterator(); it.hasNext();) {
851
              HistoryFolder folder = (HistoryFolder) it.next();
852
              Object[] children = folder.getChildren();
853
              if(children.length==1) {
854
                  LogEntryChangePath changePath = (LogEntryChangePath)children[0];
855
                  groups.add(new HistoryFolder(changePath));
856
              } else if(children.length>1) {
857
                  groups.add(folder);
858
              }
859
          }
860
          
861
          return groups.toArray();
862
      }
863
864
      private String getFolderName(LogEntryChangePath changePath) {
865
        String path = changePath.getPath();
866
        int n = path.lastIndexOf('/');
867
        return n>-1 ? path.substring(0, n) : path;
868
      }
869
870
      public void dispose() {
871
      }
872
873
      public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
874
          currentLogEntryChangePath = null;
875
      }
876
      
877
  }
878
    
879
}
(-)C:/dev/eclipse/org.tigris.subversion.subclipse.ui/src/org/tigris/subversion/subclipse/ui/history/SVNHistoryPageSource.java (+21 lines)
Line 0 Link Here
1
2
package org.tigris.subversion.subclipse.ui.history;
3
4
import org.eclipse.core.resources.IResource;
5
import org.eclipse.team.ui.history.HistoryPageSource;
6
import org.eclipse.ui.part.Page;
7
8
9
public class SVNHistoryPageSource extends HistoryPageSource {
10
11
  public boolean canShowHistoryFor(Object object) {
12
    return object instanceof IResource && ((IResource) object).getType() != IResource.ROOT;
13
  }
14
15
  public Page createPage(Object object) {
16
    SVNHistoryPage page = new SVNHistoryPage(object);
17
    return page;
18
  }
19
20
}
21
(-)C:/dev/eclipse/org.tigris.subversion.subclipse.ui/src/org/tigris/subversion/subclipse/ui/repository/model/SVNAdapterFactory.java (-1 / +9 lines)
Lines 13-18 Link Here
13
13
14
14
15
import org.eclipse.core.runtime.IAdapterFactory;
15
import org.eclipse.core.runtime.IAdapterFactory;
16
import org.eclipse.team.ui.history.IHistoryPageSource;
16
import org.eclipse.ui.model.IWorkbenchAdapter;
17
import org.eclipse.ui.model.IWorkbenchAdapter;
17
import org.eclipse.ui.progress.IDeferredWorkbenchAdapter;
18
import org.eclipse.ui.progress.IDeferredWorkbenchAdapter;
18
import org.eclipse.ui.views.properties.IPropertySource;
19
import org.eclipse.ui.views.properties.IPropertySource;
Lines 20-25 Link Here
20
import org.tigris.subversion.subclipse.core.ISVNRemoteFolder;
21
import org.tigris.subversion.subclipse.core.ISVNRemoteFolder;
21
import org.tigris.subversion.subclipse.core.ISVNRemoteResource;
22
import org.tigris.subversion.subclipse.core.ISVNRemoteResource;
22
import org.tigris.subversion.subclipse.core.ISVNRepositoryLocation;
23
import org.tigris.subversion.subclipse.core.ISVNRepositoryLocation;
24
import org.tigris.subversion.subclipse.ui.history.SVNHistoryPageSource;
23
import org.tigris.subversion.subclipse.ui.repository.properties.SVNRemoteResourcePropertySource;
25
import org.tigris.subversion.subclipse.ui.repository.properties.SVNRemoteResourcePropertySource;
24
26
25
public class SVNAdapterFactory implements IAdapterFactory {
27
public class SVNAdapterFactory implements IAdapterFactory {
Lines 26-31 Link Here
26
	private Object fileAdapter = new RemoteFileElement();
28
	private Object fileAdapter = new RemoteFileElement();
27
	private Object folderAdapter = new RemoteFolderElement();
29
	private Object folderAdapter = new RemoteFolderElement();
28
	private Object rootAdapter = new SVNRepositoryRootElement();
30
	private Object rootAdapter = new SVNRepositoryRootElement();
31
	private Object pageHistoryParticipant = new SVNHistoryPageSource();
29
32
30
	// Property cache
33
	// Property cache
31
	private Object cachedPropertyObject = null;
34
	private Object cachedPropertyObject = null;
Lines 51-56 Link Here
51
		if (IPropertySource.class == adapterType) {
54
		if (IPropertySource.class == adapterType) {
52
			return getPropertySource(adaptableObject);
55
			return getPropertySource(adaptableObject);
53
		}
56
		}
57
        
58
        if(IHistoryPageSource.class == adapterType) {
59
          return pageHistoryParticipant;
60
        }
61
        
54
		return null;
62
		return null;
55
	}
63
	}
56
64
Lines 68-74 Link Here
68
	 * Method declared on IAdapterFactory.
76
	 * Method declared on IAdapterFactory.
69
	 */
77
	 */
70
	public Class[] getAdapterList() {
78
	public Class[] getAdapterList() {
71
		return new Class[] {IWorkbenchAdapter.class, IPropertySource.class, IDeferredWorkbenchAdapter.class};
79
		return new Class[] {IWorkbenchAdapter.class, IPropertySource.class, IDeferredWorkbenchAdapter.class, IHistoryPageSource.class};
72
	}
80
	}
73
	/**
81
	/**
74
	 * Returns the property source for the given object.  Caches
82
	 * Returns the property source for the given object.  Caches

Return to bug 143354