com.google.gerrit.client.diff.SideBySideCommentGroup.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gerrit.client.diff.SideBySideCommentGroup.java

Source

// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.client.diff;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import java.util.PriorityQueue;
import net.codemirror.lib.CodeMirror;

/**
 * LineWidget attached to a CodeMirror container.
 *
 * <p>When a comment is placed on a line a CommentWidget is created on both sides. The group tracks
 * all comment boxes on that same line, and also includes an empty padding element to keep
 * subsequent lines vertically aligned.
 */
class SideBySideCommentGroup extends CommentGroup implements Comparable<SideBySideCommentGroup> {
    static void pair(SideBySideCommentGroup a, SideBySideCommentGroup b) {
        a.peers.add(b);
        b.peers.add(a);
    }

    private final Element padding;
    private final PriorityQueue<SideBySideCommentGroup> peers;

    SideBySideCommentGroup(SideBySideCommentManager manager, CodeMirror cm, DisplaySide side, int line) {
        super(manager, cm, side, line);

        padding = DOM.createDiv();
        padding.setClassName(SideBySideTable.style.padding());
        SideBySideChunkManager.focusOnClick(padding, cm.side());
        getElement().appendChild(padding);
        peers = new PriorityQueue<>();
    }

    SideBySideCommentGroup getPeer() {
        return peers.peek();
    }

    @Override
    void remove(DraftBox box) {
        super.remove(box);

        if (getBoxCount() == 0 && peers.size() == 1 && peers.peek().peers.size() > 1) {
            SideBySideCommentGroup peer = peers.peek();
            peer.peers.remove(this);
            detach();
            if (peer.getBoxCount() == 0 && peer.peers.size() == 1 && peer.peers.peek().getBoxCount() == 0) {
                peer.detach();
            } else {
                peer.resize();
            }
        } else {
            resize();
        }
    }

    @Override
    void init(DiffTable parent) {
        if (getLineWidget() == null) {
            attach(parent);
        }
        for (CommentGroup peer : peers) {
            if (peer.getLineWidget() == null) {
                peer.attach(parent);
            }
        }
    }

    @Override
    void handleRedraw() {
        getLineWidget().onRedraw(() -> {
            if (canComputeHeight() && peers.peek().canComputeHeight()) {
                if (getResizeTimer() != null) {
                    getResizeTimer().cancel();
                    setResizeTimer(null);
                }
                adjustPadding(SideBySideCommentGroup.this, peers.peek());
            } else if (getResizeTimer() == null) {
                setResizeTimer(new Timer() {
                    @Override
                    public void run() {
                        if (canComputeHeight() && peers.peek().canComputeHeight()) {
                            cancel();
                            setResizeTimer(null);
                            adjustPadding(SideBySideCommentGroup.this, peers.peek());
                        }
                    }
                });
                getResizeTimer().scheduleRepeating(5);
            }
        });
    }

    @Override
    void resize() {
        if (getLineWidget() != null) {
            adjustPadding(this, peers.peek());
        }
    }

    private int computeHeight() {
        if (getComments().isVisible()) {
            // Include margin-bottom: 5px from CSS class.
            return getComments().getOffsetHeight() + 5;
        }
        return 0;
    }

    private static void adjustPadding(SideBySideCommentGroup a, SideBySideCommentGroup b) {
        int apx = a.computeHeight();
        int bpx = b.computeHeight();
        for (SideBySideCommentGroup otherPeer : a.peers) {
            if (otherPeer != b) {
                bpx += otherPeer.computeHeight();
            }
        }
        for (SideBySideCommentGroup otherPeer : b.peers) {
            if (otherPeer != a) {
                apx += otherPeer.computeHeight();
            }
        }
        int h = Math.max(apx, bpx);
        a.padding.getStyle().setHeight(Math.max(0, h - apx), Unit.PX);
        b.padding.getStyle().setHeight(Math.max(0, h - bpx), Unit.PX);
        a.getLineWidget().changed();
        b.getLineWidget().changed();
        a.updateSelection();
        b.updateSelection();
    }

    @Override
    public int compareTo(SideBySideCommentGroup o) {
        if (side == o.side) {
            return line - o.line;
        }
        throw new IllegalStateException("Cannot compare SideBySideCommentGroup with different sides");
    }
}