Java tutorial
/******************************************************************************* * Copyright (c) 2011 Robert Munteanu and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Robert Munteanu - initial API and implementation *******************************************************************************/ package org.review_board.ereviewboard.ui.editor; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.CompareUI; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.layout.RowLayoutFactory; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider; import org.eclipse.jface.viewers.IOpenListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.OpenEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.mylyn.internal.reviews.ui.compare.FileItemCompareEditorInput; import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil; import org.eclipse.mylyn.reviews.core.model.IFileItem; import org.eclipse.mylyn.reviews.core.model.IFileVersion; import org.eclipse.mylyn.reviews.ui.ReviewUi; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.ui.TasksUi; import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPart; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.events.ExpansionAdapter; import org.eclipse.ui.forms.events.ExpansionEvent; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; import org.review_board.ereviewboard.core.ReviewboardCorePlugin; import org.review_board.ereviewboard.core.ReviewboardDiffMapper; import org.review_board.ereviewboard.core.ReviewboardTaskMapper; import org.review_board.ereviewboard.core.client.ReviewboardClient; import org.review_board.ereviewboard.core.internal.scm.SCMFileContentsLocator; import org.review_board.ereviewboard.core.model.FileDiff; import org.review_board.ereviewboard.core.model.Repository; import org.review_board.ereviewboard.core.model.reviews.ReviewModelFactory; import org.review_board.ereviewboard.core.model.reviews.TopicAddedListener; import org.review_board.ereviewboard.ui.ReviewboardUiPlugin; import org.review_board.ereviewboard.ui.editor.ext.ICompareEditorInputFactory; import org.review_board.ereviewboard.ui.editor.ext.TaskDiffAction; import org.review_board.ereviewboard.ui.util.Labels; /** * @author Robert Munteanu * */ public class ReviewboardDiffPart extends AbstractTaskEditorPart { private static final String EXTENSION_POINT_TASK_DIFF_ACTIONS = "org.review_board.ereviewboard.ui.taskDiffActions"; private static final String EXTENSION_POINT_SCM_FILE_CONTENTS_LOCATOR = "org.review_board.ereviewboard.ui.scmFileContentsLocator"; protected static final String EXTENSION_POINT_EDITOR_INPUT = "org.review_board.ereviewboard.ui.compareEditorInput"; public ReviewboardDiffPart() { setPartName("Diff"); } private void addDescriptiveRow(String name, String value, FormToolkit toolkit, Composite composite) { Label authorLabel = new Label(composite, SWT.NONE); authorLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); authorLabel.setText(name); Label authorText = new Label(composite, SWT.NONE); authorText.setText(value); } @Override public void createControl(Composite parent, FormToolkit toolkit) { Section section = createSection(parent, toolkit, true); Composite composite = toolkit.createComposite(section); GridLayoutFactory.createFrom(EditorUtil.createSectionClientLayout()).applyTo(composite); final ReviewboardTaskMapper taskMapper = new ReviewboardTaskMapper(getTaskData()); final ReviewboardDiffMapper diffMapper = new ReviewboardDiffMapper(getTaskData()); ReviewModelFactory reviewModelFactory = new ReviewModelFactory(getClient()); Integer latestDiffRevisionId = diffMapper.getLatestDiffRevisionId(); for (final Integer diffRevision : diffMapper.getDiffRevisions()) { int style = ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT | ExpandableComposite.LEFT_TEXT_CLIENT_ALIGNMENT; if (diffRevision.equals(latestDiffRevisionId)) style |= ExpandableComposite.EXPANDED; createSubsection(toolkit, composite, taskMapper, diffMapper, reviewModelFactory, diffRevision, style); } installExtensions(composite, taskMapper.getRepository(), diffMapper, null); toolkit.paintBordersFor(composite); section.setClient(composite); setSection(toolkit, section); } private void createSubsection(FormToolkit toolkit, Composite composite, final ReviewboardTaskMapper taskMapper, final ReviewboardDiffMapper diffMapper, final ReviewModelFactory reviewModelFactory, final Integer diffRevision, int style) { final Section subSection = toolkit.createSection(composite, style); GridDataFactory.fillDefaults().grab(true, false).applyTo(subSection); subSection.setText(NLS.bind("Revision {0}", diffRevision)); Composite subComposite = toolkit.createComposite(subSection); GridLayoutFactory.createFrom(EditorUtil.createSectionClientLayout()).numColumns(2).applyTo(subComposite); GridDataFactory.fillDefaults().applyTo(subComposite); subSection.setClient(subComposite); String changesText = Labels.commentsAndDrafts(diffMapper.getNumberOfPublicComments(diffRevision), diffMapper.getNumberOfDraftComments(diffRevision)); addTextClient(toolkit, subSection, changesText); addDescriptiveRow("Author", reviewModelFactory.createUser(taskMapper.getReporter()).getDisplayName(), toolkit, subComposite); addDescriptiveRow("Created", diffMapper.getTimestamp(diffRevision), toolkit, subComposite); TableViewer diffTableViewer = new TableViewer(subComposite, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL); diffTableViewer.setContentProvider(new ArrayContentProvider()); diffTableViewer.setLabelProvider( new DelegatingStyledCellLabelProvider(new ReviewboardFileDiffLabelProvider(diffMapper))); GridDataFactory.fillDefaults().span(2, 1).grab(true, true).hint(500, SWT.DEFAULT) .applyTo(diffTableViewer.getControl()); final TopicAddedListener listener = new RefreshEditorTopicAddedListener(getTaskEditorPage()); List<IFileItem> fileItems = reviewModelFactory.createFileItems(taskMapper.getReporter(), diffMapper, diffRevision); diffTableViewer.setInput(fileItems.toArray(new IFileItem[fileItems.size()])); diffTableViewer.addOpenListener(new IOpenListener() { public void open(OpenEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); IFileItem item = (IFileItem) selection.getFirstElement(); if (FileDiff.DEV_NULL.equals(item.getName())) { MessageDialog.openWarning(null, "Unable to open diff", "The diff for this file can not be generated as it has been deleted."); return; } ReviewUi.setActiveReview(new ReviewboardReviewBehaviour(getTaskEditorPage().getTask(), item, diffRevision, getClient(), reviewModelFactory, listener)); SCMFileContentsLocator baseLocator = getSCMFileContentsLocator(taskMapper, item.getBase()); if (baseLocator == null) { MessageDialog.openWarning(null, "Unable to load base file", "Unable to load base file contents since no plug-in was able to handle the repository " + taskMapper.getRepository()); return; } SCMFileContentsLocator targetLocator = getSCMFileContentsLocator(taskMapper, item.getTarget()); if (targetLocator == null) { MessageDialog.openWarning(null, "Unable to load target file", "Unable to load target file contents since no plug-in was able to handle the repository " + taskMapper.getRepository() + " The patch from the server will be used instead."); } ReviewboardReviewBehaviour reviewBehaviour = new ReviewboardReviewBehaviour( getTaskEditorPage().getTask(), item, diffRevision, getClient(), reviewModelFactory, listener); CompareUI.openCompareEditor( getCompareEditorInput(diffRevision, item, baseLocator, targetLocator, reviewBehaviour)); } private CompareEditorInput getCompareEditorInput(final Integer diffRevision, IFileItem item, SCMFileContentsLocator baseLocator, SCMFileContentsLocator targetLocator, ReviewboardReviewBehaviour reviewBehaviour) { IConfigurationElement[] configurationElements = Platform.getExtensionRegistry() .getConfigurationElementsFor(EXTENSION_POINT_EDITOR_INPUT); for (IConfigurationElement ce : configurationElements) { if (taskMapper.getRepository().getTool().getDisplayName() .equals(ce.getAttribute("repositoryType"))) { try { final Object o = ce.createExecutableExtension("class"); if (o instanceof ICompareEditorInputFactory) { ICompareEditorInputFactory factory = (ICompareEditorInputFactory) o; if (factory.isEnabled(taskMapper.getRepository())) { return factory.createInput(item, reviewBehaviour, getTaskData(), baseLocator, targetLocator, diffRevision); } } } catch (CoreException e) { // ignore silently } } } return new ReviewboardCompareEditorInput(item, reviewBehaviour, getTaskData(), baseLocator, targetLocator, diffRevision); } }); installExtensions(subComposite, taskMapper.getRepository(), diffMapper, diffRevision); } private void installExtensions(Composite composite, Repository codeRepository, ReviewboardDiffMapper diffMapper, Integer diffRevisionId) { IConfigurationElement[] configurationElements = Platform.getExtensionRegistry() .getConfigurationElementsFor(EXTENSION_POINT_TASK_DIFF_ACTIONS); int reviewRequestId = Integer.parseInt(getTaskData().getTaskId()); Map<String, TaskDiffAction> taskDiffActions = new LinkedHashMap<String, TaskDiffAction>( configurationElements.length); for (IConfigurationElement element : configurationElements) { try { final TaskDiffAction taskDiffAction = (TaskDiffAction) element.createExecutableExtension("class"); taskDiffAction.init(getTaskRepository(), reviewRequestId, codeRepository, diffMapper, diffRevisionId); if (!taskDiffAction.isEnabled()) continue; String label = element.getAttribute("label"); taskDiffActions.put(label, taskDiffAction); } catch (CoreException e) { ReviewboardUiPlugin.getDefault().getLog().log(e.getStatus()); } } if (taskDiffActions.isEmpty()) return; Composite extensionsComposite = new Composite(composite, SWT.NONE); RowLayoutFactory.fillDefaults().type(SWT.HORIZONTAL).applyTo(extensionsComposite); for (final Map.Entry<String, TaskDiffAction> taskDiffAction : taskDiffActions.entrySet()) { final String labelTest = taskDiffAction.getKey(); Button button = new Button(extensionsComposite, SWT.PUSH); button.setText(labelTest); button.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { IStatus status; try { status = taskDiffAction.getValue().execute(new NullProgressMonitor()); } catch (Exception e1) { status = new Status(IStatus.ERROR, ReviewboardUiPlugin.PLUGIN_ID, "Internal error while executing action '" + labelTest + "' : " + e1.getMessage(), e1); ReviewboardUiPlugin.getDefault().getLog().log(status); } if (!status.isOK()) { int kind = MessageDialog.ERROR; if (status.getSeverity() == IStatus.WARNING) kind = MessageDialog.WARNING; MessageDialog.open(kind, null, "Error performing action", status.getMessage(), SWT.SHEET); } if (status.getCode() == TaskDiffAction.STATUS_CODE_REFRESH_REVIEW_REQUEST) org.review_board.ereviewboard.ui.util.EditorUtil.refreshEditorPage(getTaskEditorPage()); } public void widgetDefaultSelected(SelectionEvent e) { } }); } } private TaskRepository getTaskRepository() { return TasksUi.getRepositoryManager().getRepository(ReviewboardCorePlugin.REPOSITORY_KIND, getTaskData().getRepositoryUrl()); } private ReviewboardClient getClient() { return ReviewboardCorePlugin.getDefault().getConnector().getClientManager().getClient(getTaskRepository()); } private SCMFileContentsLocator getSCMFileContentsLocator(ReviewboardTaskMapper taskMapper, IFileVersion fileRevision) { IConfigurationElement[] configurationElements = Platform.getExtensionRegistry() .getConfigurationElementsFor(EXTENSION_POINT_SCM_FILE_CONTENTS_LOCATOR); for (IConfigurationElement element : configurationElements) { try { SCMFileContentsLocator locator = (SCMFileContentsLocator) element .createExecutableExtension("class"); locator.init(taskMapper.getRepository(), fileRevision.getPath(), fileRevision.getDescription()); if (locator.isEnabled()) return locator; } catch (CoreException e) { ReviewboardUiPlugin.getDefault().getLog().log(e.getStatus()); } } return null; } private Label addTextClient(final FormToolkit toolkit, final Section section, String text) { final Label label = new Label(section, SWT.NONE); label.setText(" " + text); label.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); label.setVisible(!section.isExpanded()); section.setTextClient(label); section.addExpansionListener(new ExpansionAdapter() { @Override public void expansionStateChanged(ExpansionEvent e) { label.setVisible(!section.isExpanded()); } }); return label; } }