1 14 package org.eclipse.team.internal.ccvs.ui; 15 16 import java.util.Date ; 17 18 import org.eclipse.core.resources.IFile; 19 import org.eclipse.core.runtime.IAdaptable; 20 import org.eclipse.jface.resource.ImageDescriptor; 21 import org.eclipse.jface.resource.JFaceResources; 22 import org.eclipse.jface.util.IPropertyChangeListener; 23 import org.eclipse.jface.util.PropertyChangeEvent; 24 import org.eclipse.jface.viewers.*; 25 import org.eclipse.osgi.util.NLS; 26 import org.eclipse.swt.SWT; 27 import org.eclipse.swt.events.*; 28 import org.eclipse.swt.graphics.*; 29 import org.eclipse.swt.layout.GridData; 30 import org.eclipse.swt.widgets.*; 31 import org.eclipse.team.core.history.*; 32 import org.eclipse.team.internal.ccvs.core.CVSException; 33 import org.eclipse.team.internal.ccvs.core.ICVSFile; 34 import org.eclipse.team.internal.ccvs.core.filehistory.CVSFileRevision; 35 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; 36 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; 37 import org.eclipse.team.internal.core.history.LocalFileRevision; 38 import org.eclipse.team.internal.ui.TeamUIMessages; 39 import org.eclipse.team.internal.ui.history.AbstractHistoryCategory; 40 import org.eclipse.team.internal.ui.history.DateHistoryCategory; 41 import org.eclipse.ui.PlatformUI; 42 import org.eclipse.ui.themes.ITheme; 43 44 import com.ibm.icu.text.DateFormat; 45 46 public class CVSHistoryTableProvider { 47 48 public static final String CATEGORIES_COLOR = "org.eclipse.team.cvs.ui.fontsandcolors.cvshistorypagecategories"; 50 private IFileHistory currentFileHistory; 51 private IFile workspaceFile; 52 53 TreeViewer viewer; 54 Font currentRevisionFont; 55 56 private boolean baseModified; 57 58 private static final int COL_REVISIONID = 0; 60 private static final int COL_TAGS = 1; 61 private static final int COL_DATE = 2; 62 private static final int COL_AUTHOR = 3; 63 private static final int COL_COMMENT = 4; 64 65 68 class HistoryLabelProvider extends ColumnLabelProvider { 69 70 Image dateImage = null; 71 ImageDescriptor dateDesc = null; 72 73 Image localRevImage = null; 74 ImageDescriptor localRevDesc = null; 75 76 Image remoteRevImage = null; 77 ImageDescriptor remoteRevDesc = null; 78 79 ThemeListener themeListener; 80 private DateFormat dateFormat; 81 private final int column; 82 83 public HistoryLabelProvider(int column, CVSHistoryTableProvider provider){ 84 this.column = column; 85 PlatformUI.getWorkbench().getThemeManager().addPropertyChangeListener(themeListener= new ThemeListener(provider)); 86 } 87 88 public void dispose() { 89 if (dateImage != null){ 90 dateImage.dispose(); 91 dateImage = null; 92 } 93 94 if (localRevImage != null) { 95 localRevImage.dispose(); 96 localRevImage = null; 97 } 98 99 if (remoteRevImage != null) { 100 remoteRevImage.dispose(); 101 remoteRevImage = null; 102 } 103 104 if (themeListener != null){ 105 PlatformUI.getWorkbench().getThemeManager().removePropertyChangeListener(themeListener); 106 } 107 } 108 109 112 public String getToolTipText(Object element) { 113 if (column == COL_COMMENT && !isSingleLine(element)) { 114 IFileRevision entry = adaptToFileRevision(element); 115 if (entry != null) 116 return entry.getComment(); 117 } 118 return null; 119 } 120 121 124 public boolean useNativeToolTip(Object object) { 125 return column != COL_COMMENT || isSingleLine(object); 126 } 127 128 private boolean isSingleLine(Object object) { 129 IFileRevision entry = adaptToFileRevision(object); 130 if (entry != null) 131 return entry.getComment() == null || entry.getComment().indexOf('\n') == -1; 132 return true; 133 } 134 135 138 public Image getImage(Object element) { 139 return getColumnImage(element, column); 140 } 141 142 public Image getColumnImage(Object element, int columnIndex) { 143 if (element instanceof DateHistoryCategory && 144 columnIndex == COL_REVISIONID){ 145 if (dateImage == null){ 146 dateDesc = CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_DATES_CATEGORY); 147 dateImage = dateDesc.createImage(); 148 } 149 return dateImage; 150 } 151 152 if (element instanceof LocalFileRevision && 153 columnIndex == COL_REVISIONID){ 154 if (localRevImage == null){ 155 localRevDesc = CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_LOCALREVISION_TABLE); 156 localRevImage = localRevDesc.createImage(); 157 } 158 return localRevImage; 159 } 160 161 if (element instanceof CVSFileRevision && 162 columnIndex == COL_REVISIONID){ 163 if (remoteRevImage == null){ 164 remoteRevDesc = CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_REMOTEREVISION_TABLE); 165 remoteRevImage = remoteRevDesc.createImage(); 166 } 167 return remoteRevImage; 168 } 169 return null; 170 } 171 172 173 176 public String getText(Object element) { 177 return getColumnText(element, column); 178 } 179 180 public String getColumnText(Object element, int columnIndex) { 181 if (element instanceof AbstractHistoryCategory){ 182 if (columnIndex != COL_REVISIONID) 183 return ""; 185 return ((AbstractHistoryCategory) element).getName(); 186 } 187 188 IFileRevision entry = adaptToFileRevision(element); 189 if (entry == null) 190 return ""; switch (columnIndex) { 192 case COL_REVISIONID : 193 String revision = entry.getContentIdentifier(); 194 String currentRevision = getCurrentRevision(); 195 if (currentRevision != null && currentRevision.equals(revision)) { 196 if (baseModified) 197 revision = NLS.bind(CVSUIMessages.nameAndRevision, new String [] { revision, CVSUIMessages.CVSHistoryTableProvider_base}); else 199 revision = NLS.bind(CVSUIMessages.currentRevision, new String [] {revision}); } 201 return revision; 202 case COL_TAGS: 203 ITag[] tags = entry.getTags(); 204 StringBuffer result = new StringBuffer (); 205 for (int i = 0; i < tags.length; i++) { 206 result.append(tags[i].getName()); 207 if (i < tags.length - 1) { 208 result.append(", "); } 210 } 211 return result.toString(); 212 case COL_DATE : 213 long date = entry.getTimestamp(); 214 Date dateFromLong = new Date (date); 215 return getDateFormat().format(dateFromLong); 216 case COL_AUTHOR : 217 return entry.getAuthor(); 218 case COL_COMMENT : 219 return getCommentAsSingleLine(entry); 220 } 221 return ""; } 223 224 private synchronized DateFormat getDateFormat() { 225 if (dateFormat == null) 226 dateFormat = DateFormat.getInstance(); 227 return dateFormat; 228 } 229 230 233 public Color getForeground(Object element) { 234 if (element instanceof AbstractHistoryCategory){ 235 ITheme current = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); 236 return current.getColorRegistry().get(CVSHistoryTableProvider.CATEGORIES_COLOR); 237 } 238 239 IFileRevision entry = adaptToFileRevision(element); 240 if (!entry.exists()) { 241 return Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW); 242 } 243 244 return null; 245 } 246 247 250 public Color getBackground(Object element) { 251 return null; 252 } 253 254 258 public Font getFont(Object element) { 259 if (element instanceof AbstractHistoryCategory) { 260 return getCurrentRevisionFont(); 261 } 262 263 IFileRevision entry = adaptToFileRevision(element); 264 if (entry == null) 265 return null; 266 String revision = entry.getContentIdentifier(); 267 String tempCurrentRevision = getCurrentRevision(); 269 Font returnFont = null; 270 271 if (tempCurrentRevision != null && tempCurrentRevision.equals(revision)) { 272 returnFont = getCurrentRevisionFont(); 273 } 274 if (workspaceFile != null && entry instanceof LocalFileRevision) { 276 LocalFileRevision localRevision = (LocalFileRevision) entry; 277 if (localRevision.isCurrentState()) 278 return getCurrentRevisionFont(); 279 } 280 281 return returnFont; 282 } 283 284 private Font getCurrentRevisionFont() { 285 if (currentRevisionFont == null) { 286 Font defaultFont = JFaceResources.getDefaultFont(); 287 FontData[] data = defaultFont.getFontData(); 288 for (int i = 0; i < data.length; i++) { 289 data[i].setStyle(SWT.BOLD); 290 } 291 currentRevisionFont = new Font(viewer.getTree().getDisplay(), data); 292 } 293 return currentRevisionFont; 294 } 295 296 } 297 298 301 class HistoryComparator extends ViewerComparator { 302 private boolean reversed = false; 303 private int columnNumber; 304 305 private VersionCollator versionCollator = new VersionCollator(); 306 307 private int[][] SORT_ORDERS_BY_COLUMN = { {COL_REVISIONID, COL_DATE, COL_AUTHOR, COL_COMMENT, COL_TAGS}, 309 {COL_TAGS, COL_DATE, COL_REVISIONID, COL_AUTHOR, COL_COMMENT}, 310 {COL_DATE, COL_REVISIONID, COL_AUTHOR, COL_COMMENT, COL_TAGS}, 311 {COL_AUTHOR, COL_REVISIONID, COL_DATE, COL_COMMENT, COL_TAGS}, 312 {COL_COMMENT, COL_REVISIONID, COL_DATE, COL_AUTHOR, COL_TAGS} 313 }; 314 315 318 public HistoryComparator(int columnNumber) { 319 this.columnNumber = columnNumber; 320 } 321 322 326 public int compare(Viewer compareViewer, Object o1, Object o2) { 327 if (o1 instanceof AbstractHistoryCategory || o2 instanceof AbstractHistoryCategory) 328 return 0; 329 330 IFileRevision e1 = adaptToFileRevision(o1); 331 IFileRevision e2 = adaptToFileRevision(o2); 332 int result = 0; 333 if (e1 == null || e2 == null) { 334 result = super.compare(compareViewer, o1, o2); 335 } else { 336 int[] columnSortOrder = SORT_ORDERS_BY_COLUMN[columnNumber]; 337 for (int i = 0; i < columnSortOrder.length; ++i) { 338 result = compareColumnValue(columnSortOrder[i], e1, e2); 339 if (result != 0) 340 break; 341 } 342 } 343 if (reversed) 344 result = -result; 345 return result; 346 } 347 348 351 int compareColumnValue(int columnNumber, IFileRevision e1, IFileRevision e2) { 352 switch (columnNumber) { 353 case 0 : 354 if (e1 instanceof LocalFileRevision || 355 e2 instanceof LocalFileRevision) { 356 long date1 = e1.getTimestamp(); 358 long date2 = e2.getTimestamp(); 359 if (date1 == date2) 360 return 0; 361 362 return date1 > date2 ? 1 : -1; 363 } 364 return versionCollator.compare(e1.getContentIdentifier(), e2.getContentIdentifier()); 365 case 1: 366 ITag[] tags1 = e1.getTags(); 367 ITag[] tags2 = e2.getTags(); 368 if (tags2.length == 0) { 369 return -1; 370 } 371 if (tags1.length == 0) { 372 return 1; 373 } 374 return getComparator().compare(tags1[0].getName(), tags2[0].getName()); 375 case 2 : 376 long date1 = e1.getTimestamp(); 377 long date2 = e2.getTimestamp(); 378 if (date1 == date2) 379 return 0; 380 381 return date1 > date2 ? 1 : -1; 382 383 case 3 : 384 String author1 = e1.getAuthor(); 385 String author2 = e2.getAuthor(); 386 if (author2 == null) 387 return -1; 388 389 if (author1 == null) 390 return 1; 391 392 return getComparator().compare(author1, author2); 393 case 4 : 394 String comment1 = e1.getComment(); 395 String comment2 = e2.getComment(); 396 if (comment2 == null) 397 return -1; 398 399 if (comment1 == null) 400 return 1; 401 402 return getComparator().compare(comment1, comment2); 403 default : 404 return 0; 405 } 406 } 407 408 411 public int getColumnNumber() { 412 return columnNumber; 413 } 414 415 419 public boolean isReversed() { 420 return reversed; 421 } 422 423 426 public void setReversed(boolean newReversed) { 427 reversed = newReversed; 428 } 429 } 430 431 protected IFileRevision adaptToFileRevision(Object element) { 432 IFileRevision entry = null; 434 if (element instanceof IFileRevision) { 435 entry = (IFileRevision) element; 436 } else if (element instanceof IAdaptable) { 437 entry = (IFileRevision) ((IAdaptable) element).getAdapter(IFileRevision.class); 438 } else if (element instanceof AbstractHistoryCategory){ 439 entry = ((AbstractHistoryCategory) element).getRevisions()[0]; 440 } 441 return entry; 442 } 443 444 451 public TreeViewer createTree(Composite parent, boolean localIsDisplayed) { 452 Tree tree = new Tree(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); 453 tree.setHeaderVisible(true); 454 tree.setLinesVisible(true); 455 456 GridData data = new GridData(GridData.FILL_BOTH); 457 tree.setLayoutData(data); 458 459 TableLayout layout = new TableLayout(); 460 tree.setLayout(layout); 461 462 this.viewer = new TreeViewer(tree); 463 createColumns(viewer, layout); 464 465 ColumnViewerToolTipSupport.enableFor(viewer); 467 setLocalRevisionsDisplayed(localIsDisplayed); 468 469 tree.addDisposeListener(new DisposeListener() { 470 public void widgetDisposed(DisposeEvent e) { 471 if (currentRevisionFont != null) { 472 currentRevisionFont.dispose(); 473 } 474 } 475 }); 476 477 return viewer; 478 } 479 480 483 private void createColumns(TreeViewer tree, TableLayout layout) { 484 SelectionListener headerListener = getColumnListener(viewer); 485 486 TreeViewerColumn viewerCol = new TreeViewerColumn(tree, SWT.NONE); 488 viewerCol.setLabelProvider(new HistoryLabelProvider(COL_REVISIONID, this)); 489 TreeColumn col = viewerCol.getColumn(); 490 col.setResizable(true); 491 col.setText(TeamUIMessages.GenericHistoryTableProvider_Revision); 492 col.addSelectionListener(headerListener); 493 layout.addColumnData(new ColumnWeightData(20, true)); 494 495 viewerCol = new TreeViewerColumn(tree, SWT.NONE); 497 viewerCol.setLabelProvider(new HistoryLabelProvider(COL_TAGS, this)); 498 col = viewerCol.getColumn(); 499 col.setResizable(true); 500 col.setText(CVSUIMessages.HistoryView_tags); 501 col.addSelectionListener(headerListener); 502 layout.addColumnData(new ColumnWeightData(20, true)); 503 viewerCol = new TreeViewerColumn(tree, SWT.NONE); 505 viewerCol.setLabelProvider(new HistoryLabelProvider(COL_DATE, this)); 506 col = viewerCol.getColumn(); 507 col.setResizable(true); 508 col.setText(TeamUIMessages.GenericHistoryTableProvider_RevisionTime); 509 col.addSelectionListener(headerListener); 510 layout.addColumnData(new ColumnWeightData(20, true)); 511 512 viewerCol = new TreeViewerColumn(tree, SWT.NONE); 514 viewerCol.setLabelProvider(new HistoryLabelProvider(COL_AUTHOR, this)); 515 col = viewerCol.getColumn(); 516 col.setResizable(true); 517 col.setText(TeamUIMessages.GenericHistoryTableProvider_Author); 518 col.addSelectionListener(headerListener); 519 layout.addColumnData(new ColumnWeightData(20, true)); 520 521 viewerCol = new TreeViewerColumn(tree, SWT.NONE); 523 viewerCol.setLabelProvider(new HistoryLabelProvider(COL_COMMENT, this)); 524 col = viewerCol.getColumn(); 525 col.setResizable(true); 526 col.setText(TeamUIMessages.GenericHistoryTableProvider_Comment); 527 col.addSelectionListener(headerListener); 528 layout.addColumnData(new ColumnWeightData(50, true)); 529 } 530 531 534 private SelectionListener getColumnListener(final TreeViewer treeViewer) { 535 542 return new SelectionAdapter() { 543 552 public void widgetSelected(SelectionEvent e) { 553 int column = treeViewer.getTree().indexOf((TreeColumn) e.widget); 555 HistoryComparator oldSorter = (HistoryComparator) treeViewer.getComparator(); 556 TreeColumn treeColumn = ((TreeColumn)e.widget); 557 if (oldSorter != null && column == oldSorter.getColumnNumber()) { 558 oldSorter.setReversed(!oldSorter.isReversed()); 559 560 treeViewer.getTree().setSortColumn(treeColumn); 561 treeViewer.getTree().setSortDirection(oldSorter.isReversed() ? SWT.DOWN : SWT.UP); 562 treeViewer.refresh(); 563 } else { 564 treeViewer.getTree().setSortColumn(treeColumn); 565 treeViewer.getTree().setSortDirection(SWT.UP); 566 treeViewer.setComparator(new HistoryComparator(column)); 567 } 568 } 569 }; 570 } 571 572 public void setFile(IFileHistory fileHistory, IFile workspaceFile) { 573 this.currentFileHistory = fileHistory; 574 this.workspaceFile = workspaceFile; 575 } 576 577 578 public IFileHistory getIFileHistory() { 579 return this.currentFileHistory; 580 } 581 582 public String getCurrentRevision() { 583 584 try { 585 if (workspaceFile != null) { 586 ICVSFile cvsWorkspaceFile = CVSWorkspaceRoot.getCVSFileFor(workspaceFile); 587 byte[] syncBytes = cvsWorkspaceFile.getSyncBytes(); 588 if (syncBytes != null) { 589 String workspaceRevision = ResourceSyncInfo.getRevision(syncBytes); 590 return workspaceRevision; 591 } 592 } 593 594 } catch (CVSException e) { 595 } 596 597 return null; 598 } 599 600 605 public void setLocalRevisionsDisplayed(boolean displayed){ 606 int column = COL_REVISIONID; 608 if (displayed){ 609 column = COL_DATE; 611 } 612 613 HistoryComparator oldSorter = (HistoryComparator) viewer.getComparator(); 614 if (oldSorter != null && column == oldSorter.getColumnNumber()) { 615 viewer.refresh(); 616 } else { 617 HistoryComparator newSorter = new HistoryComparator(column); 618 newSorter.setReversed(true); 619 viewer.setComparator(newSorter); 620 viewer.getTree().setSortColumn(viewer.getTree().getColumn(column)); 621 viewer.getTree().setSortDirection(newSorter.isReversed() ? SWT.DOWN : SWT.UP); 622 623 } 624 } 625 626 public void setBaseModified(boolean modified) { 627 this.baseModified=modified; 628 } 629 630 private static class ThemeListener implements IPropertyChangeListener { 631 632 private final CVSHistoryTableProvider provider; 633 634 ThemeListener(CVSHistoryTableProvider provider) { 635 this.provider= provider; 636 } 637 public void propertyChange(PropertyChangeEvent event) { 638 provider.viewer.refresh(); 639 } 640 } 641 642 public void setWorkspaceFile(IFile workspaceFile) { 643 this.workspaceFile = workspaceFile; 644 } 645 646 public static String getCommentAsSingleLine(IFileRevision entry) { 647 String comment = entry.getComment(); 648 if (comment != null){ 649 int index = comment.indexOf("\n"); switch (index) { 651 case -1: 652 return comment; 653 case 0: 654 return CVSUIMessages.HistoryView_______4; 655 default: 656 return NLS.bind(CVSUIMessages.CVSCompareRevisionsInput_truncate, new String [] { comment.substring(0, index) }); 657 } 658 } 659 return ""; } 661 } 662 | Popular Tags |