blob: dc212e5961e2776e9e8000515cdb524e6c95beb9 [file] [log] [blame]
// 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 net.codemirror.lib.LineWidget;
import java.util.ArrayList;
import java.util.List;
/**
* Manages paddings for CommentBoxes. Each line that may need to be padded owns
* a PaddingManager instance, which maintains a padding widget whose height
* changes as necessary. PaddingManager calculates padding by taking the
* difference of the sum of CommentBox heights on the two sides.
*
* Note that in the case of an insertion or deletion gap, A PaddingManager
* can map to a list of managers on the other side. The padding needed is then
* calculated from the sum of all their heights.
*
* TODO: Let PaddingManager also take care of the paddings introduced by
* insertions and deletions.
*/
class PaddingManager {
private List<CommentBox> comments;
private PaddingWidgetWrapper wrapper;
private List<PaddingManager> others;
PaddingManager(PaddingWidgetWrapper padding) {
comments = new ArrayList<CommentBox>();
others = new ArrayList<PaddingManager>();
this.wrapper = padding;
}
static void link(PaddingManager a, PaddingManager b) {
if (!a.others.contains(b)) {
a.others.add(b);
}
if (!b.others.contains(a)) {
b.others.add(a);
}
}
private int getMyTotalHeight() {
int total = 0;
for (CommentBox box : comments) {
/**
* This gets the height of CM's line widget div, taking the margin and
* the horizontal scrollbar into account.
*/
total += box.getSelfWidgetWrapper().getElement().getParentElement().getOffsetHeight();
}
return total;
}
/**
* If this instance is on the insertion side, its counterpart on the other
* side will map to a group of PaddingManagers on this side, so we calculate
* the group's total height instead of an individual one's.
*/
private int getGroupTotalHeight() {
if (others.size() > 1) {
return getMyTotalHeight();
} else {
return others.get(0).getOthersTotalHeight();
}
}
private int getOthersTotalHeight() {
int total = 0;
for (PaddingManager manager : others) {
total += manager.getMyTotalHeight();
}
return total;
}
private void setPaddingHeight(int height) {
SideBySide2.setHeightInPx(wrapper.element, height);
wrapper.widget.changed();
}
void resizePaddingWidget() {
if (others.isEmpty()) {
return;
}
int myHeight = getGroupTotalHeight();
int othersHeight = getOthersTotalHeight();
int paddingNeeded = othersHeight - myHeight;
if (paddingNeeded < 0) {
for (PaddingManager manager : others.get(0).others) {
manager.setPaddingHeight(0);
}
others.get(others.size() - 1).setPaddingHeight(-paddingNeeded);
} else {
setPaddingHeight(paddingNeeded);
for (PaddingManager other : others) {
other.setPaddingHeight(0);
}
}
}
/** This is unused now because threading info is ignored. */
int getReplyIndex(CommentBox box) {
return comments.indexOf(box) + 1;
}
int getCurrentCount() {
return comments.size();
}
void insert(CommentBox box, int index) {
comments.add(index, box);
}
void remove(CommentBox box) {
comments.remove(box);
}
static class PaddingWidgetWrapper {
private LineWidget widget;
private Element element;
PaddingWidgetWrapper(LineWidget w, Element e) {
widget = w;
element = e;
}
LineWidget getWidget() {
return widget;
}
Element getElement() {
return element;
}
}
static class LinePaddingWidgetWrapper extends PaddingWidgetWrapper {
private int chunkLength;
private int otherLine;
LinePaddingWidgetWrapper(PaddingWidgetWrapper pair, int otherLine, int chunkLength) {
super(pair.widget, pair.element);
this.otherLine = otherLine;
this.chunkLength = chunkLength;
}
int getChunkLength() {
return chunkLength;
}
int getOtherLine() {
return otherLine;
}
}
}