com.tasktop.c2c.server.scm.web.ui.client.view.ScmCommitView.java Source code

Java tutorial

Introduction

Here is the source code for com.tasktop.c2c.server.scm.web.ui.client.view.ScmCommitView.java

Source

/*******************************************************************************
 * Copyright (c) 2010, 2012 Tasktop Technologies
 * 
 * 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:
 *     Tasktop Technologies - initial API and implementation
 ******************************************************************************/
package com.tasktop.c2c.server.scm.web.ui.client.view;

import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.editor.ui.client.adapters.HasTextEditor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.client.SafeHtmlTemplates.Template;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DateLabel;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import com.googlecode.google_code_prettify.GoogleCodePrettifyUtil;
import com.tasktop.c2c.server.common.profile.web.client.CommonProfileMessages;
import com.tasktop.c2c.server.common.web.client.navigation.Navigation;
import com.tasktop.c2c.server.common.web.client.view.Avatar;
import com.tasktop.c2c.server.common.web.client.widgets.Format;
import com.tasktop.c2c.server.common.web.client.widgets.hyperlink.HyperlinkingLabel;
import com.tasktop.c2c.server.scm.domain.Commit;
import com.tasktop.c2c.server.scm.domain.DiffEntry;
import com.tasktop.c2c.server.scm.domain.DiffEntry.Hunk;
import com.tasktop.c2c.server.scm.web.ui.client.place.ScmCommitPlace;
import com.tasktop.c2c.server.scm.web.ui.client.place.ScmRepoPlace;
import com.tasktop.c2c.server.scm.web.ui.client.resources.ScmMessages;
import com.tasktop.c2c.server.scm.web.ui.client.resources.ScmResources;
import com.tasktop.c2c.server.tasks.client.widgets.TaskHyperlinkDetector;

/**
 * @author cmorgan (Tasktop Technologies Inc.)
 * 
 */
public class ScmCommitView extends Composite implements Editor<Commit> {

    private static ScmCommitView instance;

    public static ScmCommitView getInstance() {
        if (instance == null) {
            instance = GWT.create(ScmCommitView.class);
        }
        return instance;
    }

    interface Binder extends UiBinder<Widget, ScmCommitView> {
    }

    private static Binder uiBinder = GWT.create(Binder.class);

    interface Driver extends SimpleBeanEditorDriver<Commit, ScmCommitView> {
    }

    private Driver driver = GWT.create(Driver.class);

    protected ScmCommitView() {
        bindUI();
        initializeAfterBind();
    }

    protected void bindUI() {
        initWidget(uiBinder.createAndBindUi(this));
    }

    protected void initializeAfterBind() {
        comment = HasTextEditor.of(commentLabel);
        driver.initialize(this);
        patchPanel.getHeader().getElement().getParentElement().setClassName(""); // prevent style collision
        changesPanel.getHeader().getElement().getParentElement().setClassName(""); // prevent style collision
        commentLabel.addHyperlinkDetector(taskHyperlinkDetector);
        ScmResources.get.style().ensureInjected();

        patchPanel.getContent().removeStyleName("content");
        changesPanel.getContent().removeStyleName("content");
    }

    @UiField
    public Label commitId;
    @UiField
    @Path("author.email")
    public Label authorEmail;
    @UiField
    public Image authorImage;
    @UiField(provided = true)
    public DateLabel date = new DateLabel(Format.getDateTimeFormat());
    @UiField
    public HyperlinkingLabel commentLabel;
    private TaskHyperlinkDetector taskHyperlinkDetector = new TaskHyperlinkDetector(null);
    protected HasTextEditor comment;
    @UiField
    public Panel parentsPanel;
    @UiField
    public Panel filesPanel;
    @UiField
    public DisclosurePanel changesPanel;
    @UiField
    @Editor.Ignore
    public HTML diffHtml;
    @UiField
    public Anchor repository;
    @UiField
    public DisclosurePanel patchPanel;
    @UiField
    public DivElement committerInfoDiv;
    @UiField
    @Ignore
    public Label committedByLabel;
    protected String projectId;

    private final int maxPrettifiableLines = 1000;
    private int totalDiffLines;
    private CommonProfileMessages commonProfileMessages = GWT.create(CommonProfileMessages.class);
    private ScmMessages scmMessages = GWT.create(ScmMessages.class);

    /**
     * @param commit
     */
    public void setCommit(Commit commit) {

        driver.edit(commit);

        repository.setText(commonProfileMessages.parentheses(commit.getRepository()));
        repository.setHref(ScmRepoPlace.createPlace(projectId, commit.getRepository()).getHref());

        parentsPanel.clear();
        if (commit.getParents().isEmpty()) {
            parentsPanel.add(new Label("None"));
        } else {
            boolean needSep = false;
            for (String parentId : commit.getParents()) {
                if (needSep) {
                    parentsPanel.add(new Label(commonProfileMessages.comma()));
                } else {
                    needSep = true;
                }
                parentsPanel.add(new Anchor(Commit.minimizeCommitId(parentId),
                        ScmCommitPlace.createPlace(projectId, commit.getRepository(), parentId).getHref()));
            }
        }

        filesPanel.clear();

        if (commit.getChanges() != null) {
            int i = 0;
            for (DiffEntry diffEntry : commit.getChanges()) {
                DiffEntryView overviewFileDiff = new DiffEntryView(diffEntry);
                filesPanel.add(overviewFileDiff);

                final int index = i++;
                overviewFileDiff.getFileNameAnchor().addClickHandler(new ClickHandler() {

                    @Override
                    public void onClick(ClickEvent event) {

                        if (!patchPanel.isOpen()) {
                            patchPanel.setOpen(true);
                        }
                        Element toScrollTo = Navigation.findElementById(diffHtml.getElement(),
                                computeElementId(index));
                        if (toScrollTo != null) {
                            Window.scrollTo(0, toScrollTo.getAbsoluteTop());
                        }

                    }
                });
            }
            patchPanel.setVisible(true);
            changesPanel.setVisible(true);
            diffHtml.setHTML(buildHtml(commit.getChanges()));
        } else {
            patchPanel.setVisible(false);
            changesPanel.setVisible(false);
            diffHtml.setHTML("");
        }

        authorImage.setUrl(Avatar.computeAvatarUrl(commit.getAuthor().getGravatarHash(), Avatar.Size.MEDIUM));

        UIObject.setVisible(committerInfoDiv, commit.getCommitter() != null);
        if (commit.getCommitter() != null) {
            committedByLabel.setText(scmMessages.committedByOn(commit.getCommitter().getEmail(),
                    Format.getDateTimeFormat().format(commit.getCommitDate())));
        }
        if (totalDiffLines < maxPrettifiableLines) {
            GoogleCodePrettifyUtil.run();
        }
    }

    private String computeElementId(int index) {
        return "diff-file-" + index;
    }

    static interface Template extends SafeHtmlTemplates {
        @Template("<div class=\"{0}\" id=\"{1}\">{2}</div>")
        SafeHtml addFileChange(String style, String id, String filename);

        @Template("<pre class=\"prettyprint {0}\">{1}</pre>")
        SafeHtml content(String style, String content);

        @Template("<pre class=\"prettyprint {0}\">@@ -{1},{2} +{3},{4} @@</pre>")
        SafeHtml hunk(String style, int aS, int aE, int bS, int bE);

        @Template("<pre class=\"prettyprint {0}\">Binary files differ</pre>")
        SafeHtml binary(String style);

    }

    private static Template template = GWT.create(Template.class);

    private SafeHtml buildHtml(List<DiffEntry> changes) {
        SafeHtmlBuilder htmlBuilder = new SafeHtmlBuilder();
        String fileName;
        int i = 0;
        totalDiffLines = 0;
        for (DiffEntry diff : changes) {
            totalDiffLines = totalDiffLines + diff.getLinesAdded() + diff.getLinesRemoved();
            String elId = computeElementId(i++);
            switch (diff.getChangeType()) {
            case ADD:
            case MODIFY:
                fileName = diff.getNewPath();
                break;
            case DELETE:
                fileName = diff.getOldPath();
                break;
            case RENAME:
                fileName = scmMessages.renamedTo(diff.getOldPath(), diff.getNewPath());
                break;
            case COPY:
                fileName = scmMessages.copiedTo(diff.getOldPath(), diff.getNewPath());
                break;
            default:
                fileName = diff.getNewPath();
                break;
            }

            htmlBuilder
                    .append(template.addFileChange(ScmResources.get.style().contentFileHeader(), elId, fileName));

            if (diff.isBinary()) {
                htmlBuilder.append(template.binary(""));
            } else {
                for (Hunk hunk : diff.getHunks()) {
                    htmlBuilder.append(template.hunk("", hunk.getAStartLine(), hunk.getAEndLine(),
                            hunk.getBStartLine(), hunk.getBEndLine()));

                    String style = null;
                    char prefix = ' ';
                    StringBuilder content = null;
                    Hunk.LineChange.Type lt = null;

                    for (Hunk.LineChange lc : hunk.getLineChanges()) {

                        if (lc.getType() != lt) {

                            if (content != null) {
                                htmlBuilder.append(template.content(style, content.toString()));
                            }

                            content = new StringBuilder();
                            lt = lc.getType();
                            switch (lc.getType()) {
                            case ADDED:
                                style = ScmResources.get.style().contentAdded();
                                prefix = '+';
                                break;
                            case REMOVED:
                                prefix = '-';
                                style = ScmResources.get.style().contentRemoved();
                                break;
                            default:
                                prefix = ' ';
                                style = "";
                            }
                        }

                        content.append(prefix + lc.getText() + "\n");
                    }

                    htmlBuilder.append(template.content(style, content.toString()));

                }
            }

        }
        return htmlBuilder.toSafeHtml();
    }

    public void setProjectId(String projectId) {
        this.projectId = projectId;
        taskHyperlinkDetector.setProjectIdentity(projectId);
    }

}