blob: 4972f5ddb74edf39c2d07a55116315e156da8996 [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.gerrit.client.diff.DiffInfo.Region;
import com.google.gerrit.client.patches.SkippedLine;
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
import com.google.gwt.core.client.JsArray;
import net.codemirror.lib.CodeMirror;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** Collapses common regions with {@link SkipBar} for {@link SideBySide}. */
class SkipManager {
private final SideBySide host;
private final CommentManager commentManager;
private Set<SkipBar> skipBars;
private SkipBar line0;
SkipManager(SideBySide host, CommentManager commentManager) {
this.host = host;
this.commentManager = commentManager;
}
void render(int context, DiffInfo diff) {
if (context == AccountDiffPreference.WHOLE_FILE_CONTEXT) {
return;
}
JsArray<Region> regions = diff.content();
List<SkippedLine> skips = new ArrayList<>();
int lineA = 0, lineB = 0;
for (int i = 0; i < regions.length(); i++) {
Region current = regions.get(i);
if (current.ab() != null || current.common() || current.skip() > 0) {
int len = current.skip() > 0
? current.skip()
: (current.ab() != null ? current.ab() : current.b()).length();
if (i == 0 && len > context + 1) {
skips.add(new SkippedLine(0, 0, len - context));
} else if (i == regions.length() - 1 && len > context + 1) {
skips.add(new SkippedLine(lineA + context, lineB + context,
len - context));
} else if (len > 2 * context + 1) {
skips.add(new SkippedLine(lineA + context, lineB + context,
len - 2 * context));
}
lineA += len;
lineB += len;
} else {
lineA += current.a() != null ? current.a().length() : 0;
lineB += current.b() != null ? current.b().length() : 0;
}
}
skips = commentManager.splitSkips(context, skips);
if (!skips.isEmpty()) {
CodeMirror cmA = host.getCmFromSide(DisplaySide.A);
CodeMirror cmB = host.getCmFromSide(DisplaySide.B);
skipBars = new HashSet<>();
for (SkippedLine skip : skips) {
SkipBar barA = newSkipBar(cmA, DisplaySide.A, skip);
SkipBar barB = newSkipBar(cmB, DisplaySide.B, skip);
SkipBar.link(barA, barB);
skipBars.add(barA);
skipBars.add(barB);
if (skip.getStartA() == 0 || skip.getStartB() == 0) {
barA.upArrow.setVisible(false);
barB.upArrow.setVisible(false);
line0 = barB;
} else if (skip.getStartA() + skip.getSize() == lineA
|| skip.getStartB() + skip.getSize() == lineB) {
barA.downArrow.setVisible(false);
barB.downArrow.setVisible(false);
}
}
}
}
void ensureFirstLineIsVisible() {
if (line0 != null) {
line0.expandBefore(1);
line0 = null;
}
}
void removeAll() {
if (skipBars != null) {
for (SkipBar bar : skipBars) {
bar.expandSideAll();
}
skipBars = null;
line0 = null;
}
}
void remove(SkipBar a, SkipBar b) {
skipBars.remove(a);
skipBars.remove(b);
if (line0 == a || line0 == b) {
line0 = null;
}
if (skipBars.isEmpty()) {
skipBars = null;
}
}
private SkipBar newSkipBar(CodeMirror cm, DisplaySide side, SkippedLine skip) {
int start = side == DisplaySide.A ? skip.getStartA() : skip.getStartB();
int end = start + skip.getSize() - 1;
SkipBar bar = new SkipBar(this, cm);
host.diffTable.add(bar);
bar.collapse(start, end, true);
return bar;
}
}