| /******************************************************************************* |
| * Copyright (c) 2015 Ericsson AB. |
| * 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: |
| * Jacques Bouthillier - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.egerrit.internal.ui.tabs; |
| |
| import java.text.SimpleDateFormat; |
| import java.util.Iterator; |
| |
| import org.eclipse.core.databinding.DataBindingContext; |
| import org.eclipse.core.databinding.UpdateValueStrategy; |
| import org.eclipse.core.databinding.observable.list.IObservableList; |
| import org.eclipse.core.databinding.observable.value.ComputedValue; |
| import org.eclipse.core.databinding.observable.value.IObservableValue; |
| import org.eclipse.egerrit.internal.core.EGerritCorePlugin; |
| import org.eclipse.egerrit.internal.core.GerritClient; |
| import org.eclipse.egerrit.internal.core.command.ChangeCommitMsgCommand; |
| import org.eclipse.egerrit.internal.core.command.PublishChangeEditCommand; |
| import org.eclipse.egerrit.internal.core.exception.EGerritException; |
| import org.eclipse.egerrit.internal.core.rest.ChangeEditMessageInput; |
| import org.eclipse.egerrit.internal.model.ChangeInfo; |
| import org.eclipse.egerrit.internal.model.CommitInfo; |
| import org.eclipse.egerrit.internal.model.ModelPackage; |
| import org.eclipse.egerrit.internal.ui.editors.ModelLoader; |
| import org.eclipse.egerrit.internal.ui.utils.DataConverter; |
| import org.eclipse.egerrit.internal.ui.utils.EGerritConstants; |
| import org.eclipse.egerrit.internal.ui.utils.LinkDashboard; |
| import org.eclipse.egerrit.internal.ui.utils.Messages; |
| import org.eclipse.egerrit.internal.ui.utils.UIUtils; |
| import org.eclipse.emf.databinding.EMFObservables; |
| import org.eclipse.emf.databinding.EMFProperties; |
| import org.eclipse.emf.databinding.FeaturePath; |
| import org.eclipse.jface.databinding.swt.WidgetProperties; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.ScrolledComposite; |
| import org.eclipse.swt.events.ControlAdapter; |
| import org.eclipse.swt.events.ControlEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Link; |
| import org.eclipse.swt.widgets.TabFolder; |
| import org.eclipse.swt.widgets.TabItem; |
| import org.eclipse.swt.widgets.Text; |
| |
| /** |
| * This class is used in the editor to handle the Gerrit message view |
| * |
| * @since 1.0 |
| */ |
| public class MessageTabView { |
| |
| private Text msgTextData; |
| |
| private Link msgAuthorData; |
| |
| private Label msgDatePushData; |
| |
| private Link msgCommitterData; |
| |
| private Label msgDatecommitterData; |
| |
| private Link msgCommitidData; |
| |
| private Label msgParentIdData; |
| |
| private Link msgChangeIdData; |
| |
| private final SimpleDateFormat formatTimeOut = new SimpleDateFormat("MMM d, yyyy hh:mm a"); //$NON-NLS-1$ |
| |
| private GerritClient fGerritClient; |
| |
| private ChangeInfo fChangeInfo; |
| |
| private Boolean fShowExtraInfo = true; |
| |
| private DataBindingContext bindingContext = new DataBindingContext(); |
| |
| private ObservableCollector observableCollector; |
| |
| // ------------------------------------------------------------------------ |
| // Constructor and life cycle |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * The constructor. |
| * |
| * @param changeInfo |
| * @param gerritClient |
| */ |
| public MessageTabView(GerritClient gerritClient, ChangeInfo changeInfo) { |
| fGerritClient = gerritClient; |
| fChangeInfo = changeInfo; |
| } |
| |
| /** |
| * @param GerritClient |
| * @param Composite |
| * @param ChangeInfo |
| */ |
| public void create(Composite tabFolder) { |
| |
| createControls(tabFolder); |
| } |
| |
| private boolean isEditingAllowed() { |
| return !fGerritClient.getRepository().getServerInfo().isAnonymous(); |
| } |
| |
| /** |
| * Create the top parent as a tab folder |
| * |
| * @param tabFolder |
| * @return Composite |
| */ |
| private Composite createAsTabfolder(Composite tabFolder) { |
| final TabItem tabMessages = new TabItem((TabFolder) tabFolder, SWT.NONE); |
| tabMessages.setText(Messages.MessageTabView_1); |
| |
| final Composite messagesComposite = new Composite(tabFolder, SWT.NONE); |
| tabMessages.setControl(messagesComposite); |
| messagesComposite.setLayout(new GridLayout(4, false)); |
| return messagesComposite; |
| } |
| |
| /** |
| * Create the top parent as a composite |
| * |
| * @param tabFolder |
| * @return Composite |
| */ |
| private Composite createAsComposite(Composite parent) { |
| |
| final ScrolledComposite scrollComposite = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL); |
| |
| final Composite messagesComposite = new Composite(scrollComposite, SWT.NONE); |
| messagesComposite.setLayout(new GridLayout(4, false)); |
| |
| scrollComposite.setContent(messagesComposite); |
| scrollComposite.setExpandVertical(true); |
| scrollComposite.setExpandHorizontal(true); |
| scrollComposite.addControlListener(new ControlAdapter() { |
| @Override |
| public void controlResized(ControlEvent e) { |
| scrollComposite.setMinSize(messagesComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); |
| } |
| }); |
| |
| //Do not show the Extra data |
| fShowExtraInfo = false; |
| return messagesComposite; |
| } |
| |
| private void createControls(Composite composite) { |
| final Composite messagesComposite; |
| |
| //Define the proper instance of the composite, i.e. Tabfolder or anything else |
| if (composite instanceof TabFolder) { |
| messagesComposite = createAsTabfolder(composite); |
| } else { |
| messagesComposite = createAsComposite(composite); |
| } |
| |
| msgTextData = new Text(messagesComposite, SWT.BORDER | SWT.WRAP | SWT.MULTI | SWT.V_SCROLL); |
| GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1); |
| Point fontsize = UIUtils.computeFontSize(messagesComposite); |
| gridData.minimumHeight = fontsize.y * 3;//Set a minimum height to 3 lines |
| msgTextData.setLayoutData(gridData); |
| msgTextData.setEditable(isEditingAllowed()); |
| |
| final Button btnCancel = new Button(messagesComposite, SWT.NONE); |
| GridData gdBtnCancel = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); |
| btnCancel.setLayoutData(gdBtnCancel); |
| btnCancel.setText(Messages.MessageTabView_2); |
| btnCancel.setEnabled(false); |
| |
| final Button fBtnSave = new Button(messagesComposite, SWT.NONE); |
| GridData gdBtnSave = new GridData(SWT.LEFT, SWT.TOP, false, false, 3, 1); |
| fBtnSave.setLayoutData(gdBtnSave); |
| fBtnSave.setText(Messages.MessageTabView_3); |
| fBtnSave.setEnabled(false); |
| |
| if (isEditingAllowed()) { |
| btnCancel.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| msgTextData.setText(fChangeInfo.getUserSelectedRevision().getCommit().getMessage()); |
| fBtnSave.setEnabled(false); |
| btnCancel.setEnabled(false); |
| } |
| }); |
| } |
| |
| if (isEditingAllowed()) { |
| ModifyListener textModifiedListener = event -> { |
| if (fChangeInfo.getUserSelectedRevision() != null && fChangeInfo.getUserSelectedRevision() |
| .getCommit() |
| .getMessage() |
| .compareTo(msgTextData.getText()) != 0) { |
| fBtnSave.setEnabled(true); |
| btnCancel.setEnabled(true); |
| } else { |
| fBtnSave.setEnabled(false); |
| btnCancel.setEnabled(false); |
| } |
| }; |
| msgTextData.addModifyListener(textModifiedListener); |
| } |
| |
| if (fShowExtraInfo) { |
| //LINE 1 - Author: <authorname> date |
| Label lblAuthor = new Label(messagesComposite, SWT.NONE); |
| lblAuthor.setText(Messages.MessageTabView_4); |
| lblAuthor.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); |
| |
| msgAuthorData = new Link(messagesComposite, SWT.NONE); |
| msgAuthorData.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); |
| msgAuthorData.setToolTipText(Messages.MessageTabView_7); |
| msgAuthorData.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| LinkDashboard linkDash = new LinkDashboard(fGerritClient); |
| //Need to put the text in quotes since there might be some empty spaces or special char in the user name |
| linkDash.invokeRefreshDashboardCommand(EGerritConstants.OWNER, |
| "\"" + e.text + "\"" + " status:open"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| }); |
| |
| msgDatePushData = new Label(messagesComposite, SWT.NONE); |
| msgDatePushData.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 2, 1)); |
| |
| //LINE 2 - Committer: <committername> date |
| Label lblCommitter = new Label(messagesComposite, SWT.NONE); |
| lblCommitter.setText(Messages.MessageTabView_5); |
| lblCommitter.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); |
| |
| msgCommitterData = new Link(messagesComposite, SWT.NONE); |
| msgCommitterData.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); |
| msgCommitterData.setToolTipText(Messages.MessageTabView_10); |
| msgCommitterData.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| LinkDashboard linkDash = new LinkDashboard(fGerritClient); |
| //Need to put the text in quotes since there might be some empty spaces or special char in the user name |
| linkDash.invokeRefreshDashboardCommand(EGerritConstants.OWNER, |
| "\"" + e.text + "\"" + " status:open"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| }); |
| |
| msgDatecommitterData = new Label(messagesComposite, SWT.NONE); |
| GridData gdDateCommitter = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 2, 1); |
| msgDatecommitterData.setLayoutData(gdDateCommitter); |
| |
| //LINE 3 - Commit: <commitId> |
| Label lblCommit = new Label(messagesComposite, SWT.NONE); |
| lblCommit.setText(Messages.MessageTabView_6); |
| lblCommit.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); |
| |
| msgCommitidData = new Link(messagesComposite, SWT.NONE); |
| msgCommitidData.setToolTipText(Messages.MessageTabView_11); |
| msgCommitidData.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| LinkDashboard linkDash = new LinkDashboard(fGerritClient); |
| linkDash.invokeRefreshDashboardCommand("", e.text); //$NON-NLS-1$ |
| } |
| }); |
| |
| msgCommitidData.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 3, 1)); |
| |
| //LINE 4 - Parents: <parentId> |
| Label lblParents = new Label(messagesComposite, SWT.NONE); |
| lblParents.setText(Messages.MessageTabView_8); |
| lblParents.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); |
| |
| msgParentIdData = new Label(messagesComposite, SWT.NONE); |
| msgParentIdData.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1)); |
| |
| //LINE 5 - ChangeId: <id> |
| Label lblChangeid = new Label(messagesComposite, SWT.NONE); |
| lblChangeid.setText(Messages.MessageTabView_9); |
| lblChangeid.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); |
| |
| msgChangeIdData = new Link(messagesComposite, SWT.NONE); |
| msgChangeIdData.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1)); |
| msgChangeIdData.setToolTipText(Messages.MessageTabView_12); |
| msgChangeIdData.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| LinkDashboard linkDash = new LinkDashboard(fGerritClient); |
| linkDash.invokeRefreshDashboardCommand("", e.text); //$NON-NLS-1$ |
| } |
| }); |
| } |
| |
| if (isEditingAllowed()) { |
| fBtnSave.addSelectionListener(new SelectionAdapter() { |
| /** |
| * |
| */ |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| super.widgetSelected(e); |
| ChangeCommitMsgCommand editMessageCmd = fGerritClient.editMessage(fChangeInfo.getId()); |
| ChangeEditMessageInput changeEditMessageInput = new ChangeEditMessageInput(); |
| changeEditMessageInput.setMessage(msgTextData.getText()); |
| editMessageCmd.setCommandInput(changeEditMessageInput); |
| PublishChangeEditCommand publishChangeEditCmd = fGerritClient |
| .publishChangeEdit(fChangeInfo.getId()); |
| |
| try { |
| editMessageCmd.call(); |
| publishChangeEditCmd.call(); |
| } catch (EGerritException e3) { |
| EGerritCorePlugin |
| .logError(fGerritClient.getRepository().formatGerritVersion() + e3.getMessage()); |
| } |
| fBtnSave.setEnabled(false); |
| btnCancel.setEnabled(false); |
| ModelLoader loader = ModelLoader.initialize(fGerritClient, fChangeInfo); |
| loader.loadBasicInformation(false); |
| loader.dispose(); |
| } |
| }); |
| } |
| |
| if (fShowExtraInfo) { |
| new Label(messagesComposite, SWT.NONE); |
| } |
| |
| //Set the binding for this section |
| msgTabDataBindings(); |
| } |
| |
| private void msgTabDataBindings() { |
| bindCommitMessage(); |
| if (!fShowExtraInfo) { |
| observableCollector = new ObservableCollector(bindingContext); |
| return;// Do not bind any other functionality when not shown |
| } |
| |
| bindComitAuthor(); |
| bindCommitDate(); |
| bindCommitterName(); |
| bindCommitterDate(); |
| bindCommitId(); |
| bindCommitParents(); |
| bindChangeId(); |
| observableCollector = new ObservableCollector(bindingContext); |
| } |
| |
| /** |
| * |
| */ |
| private void bindChangeId() { |
| //Show change id |
| IObservableValue<String> msgChangeIdDataValue = EMFObservables.observeValue(fChangeInfo, |
| ModelPackage.Literals.CHANGE_INFO__CHANGE_ID); |
| bindingContext.bindValue(WidgetProperties.text().observe(msgChangeIdData), msgChangeIdDataValue, null, |
| new UpdateValueStrategy().setConverter(DataConverter.linkText())); |
| } |
| |
| /** |
| * |
| */ |
| private void bindCommitParents() { |
| //show commit parents |
| FeaturePath commitParents = FeaturePath.fromList(ModelPackage.Literals.CHANGE_INFO__REVISION, |
| ModelPackage.Literals.REVISION_INFO__COMMIT, ModelPackage.Literals.COMMIT_INFO__PARENTS); |
| final IObservableList parents = EMFProperties.list(commitParents).observe(fChangeInfo); |
| ComputedValue<String> parentCommitsAsString = new ComputedValue<String>() { |
| @Override |
| protected String calculate() { |
| Iterator it = parents.iterator(); |
| StringBuilder result = new StringBuilder(); |
| while (it.hasNext()) { |
| CommitInfo info = (CommitInfo) it.next(); |
| result.append(info.getCommit()); |
| result.append(" "); //$NON-NLS-1$ |
| } |
| return result.toString().trim(); |
| } |
| }; |
| bindingContext.bindValue(WidgetProperties.text().observe(msgParentIdData), parentCommitsAsString, null, null); |
| } |
| |
| /** |
| * |
| */ |
| private void bindCommitId() { |
| //show commit id |
| final FeaturePath commitId = FeaturePath.fromList(ModelPackage.Literals.CHANGE_INFO__REVISION, |
| ModelPackage.Literals.REVISION_INFO__COMMIT, ModelPackage.Literals.COMMIT_INFO__COMMIT); |
| IObservableValue<String> msgCommitidDataValue = EMFProperties.value(commitId).observe(fChangeInfo); |
| bindingContext.bindValue(WidgetProperties.text().observe(msgCommitidData), msgCommitidDataValue, null, |
| new UpdateValueStrategy().setConverter(DataConverter.linkText())); |
| } |
| |
| /** |
| * |
| */ |
| private void bindCommitterDate() { |
| //Show committer date |
| final FeaturePath commiterDate = FeaturePath.fromList(ModelPackage.Literals.CHANGE_INFO__REVISION, |
| ModelPackage.Literals.REVISION_INFO__COMMIT, ModelPackage.Literals.COMMIT_INFO__COMMITTER, |
| ModelPackage.Literals.GIT_PERSON_INFO__DATE); |
| IObservableValue<String> msgCommitterDateDataValue = EMFProperties.value(commiterDate).observe(fChangeInfo); |
| bindingContext.bindValue(WidgetProperties.text().observe(msgDatecommitterData), msgCommitterDateDataValue, null, |
| new UpdateValueStrategy().setConverter(DataConverter.gerritTimeConverter(formatTimeOut))); |
| } |
| |
| /** |
| * |
| */ |
| private void bindCommitterName() { |
| //Show committer name |
| final FeaturePath committerName = FeaturePath.fromList(ModelPackage.Literals.CHANGE_INFO__REVISION, |
| ModelPackage.Literals.REVISION_INFO__COMMIT, ModelPackage.Literals.COMMIT_INFO__COMMITTER); |
| IObservableValue<String> msgCommitterDataValue = EMFProperties.value(committerName).observe(fChangeInfo); |
| bindingContext.bindValue(WidgetProperties.text().observe(msgCommitterData), msgCommitterDataValue, null, |
| new UpdateValueStrategy().setConverter(DataConverter.gitPersonConverter())); |
| } |
| |
| /** |
| * |
| */ |
| private void bindCommitDate() { |
| final FeaturePath commitDate = FeaturePath.fromList(ModelPackage.Literals.CHANGE_INFO__REVISION, |
| ModelPackage.Literals.REVISION_INFO__COMMIT, ModelPackage.Literals.COMMIT_INFO__AUTHOR, |
| ModelPackage.Literals.GIT_PERSON_INFO__DATE); |
| IObservableValue<String> msgAuthorDateDataValue = EMFProperties.value(commitDate).observe(fChangeInfo); |
| bindingContext.bindValue(WidgetProperties.text().observe(msgDatePushData), msgAuthorDateDataValue, null, |
| new UpdateValueStrategy().setConverter(DataConverter.gerritTimeConverter(formatTimeOut))); |
| } |
| |
| /** |
| * |
| */ |
| private void bindComitAuthor() { |
| //show commit author |
| final FeaturePath authorName = FeaturePath.fromList(ModelPackage.Literals.CHANGE_INFO__REVISION, |
| ModelPackage.Literals.REVISION_INFO__COMMIT, ModelPackage.Literals.COMMIT_INFO__AUTHOR); |
| IObservableValue<String> msgAuthorDataValue = EMFProperties.value(authorName).observe(fChangeInfo); |
| bindingContext.bindValue(WidgetProperties.text().observe(msgAuthorData), msgAuthorDataValue, null, |
| new UpdateValueStrategy().setConverter(DataConverter.gitPersonConverter())); |
| } |
| |
| /** |
| * |
| */ |
| private void bindCommitMessage() { |
| //the commit message |
| final FeaturePath commitMessage = FeaturePath.fromList(ModelPackage.Literals.CHANGE_INFO__REVISION, |
| ModelPackage.Literals.REVISION_INFO__COMMIT, ModelPackage.Literals.COMMIT_INFO__MESSAGE); |
| IObservableValue<String> msgTextDataValue = EMFProperties.value(commitMessage).observe(fChangeInfo); |
| bindingContext.bindValue(WidgetProperties.text().observe(msgTextData), msgTextDataValue, null, null); |
| } |
| |
| public void dispose() { |
| observableCollector.dispose(); |
| bindingContext.dispose(); |
| } |
| } |