// 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.extensions.client.DiffPreferencesInfo; import com.google.gwt.core.client.JsArray; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import net.codemirror.lib.CodeMirror; /** Collapses common regions with {@link SkipBar} for {@link SideBySide} and {@link Unified}. */ class SkipManager { private final Set<SkipBar> skipBars; private final DiffScreen host; private SkipBar line0; SkipManager(DiffScreen host) { this.host = host; this.skipBars = new HashSet<>(); } void render(int context, DiffInfo diff) { if (context == DiffPreferencesInfo.WHOLE_FILE_CONTEXT) { return; } List<SkippedLine> skips = new ArrayList<>(); int lineA = 0; int lineB = 0; JsArray<Region> regions = diff.content(); 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 = host.getCommentManager().splitSkips(context, skips); renderSkips(skips, lineA, lineB); } private void renderSkips(List<SkippedLine> skips, int lineA, int lineB) { if (!skips.isEmpty()) { boolean isSideBySide = host.isSideBySide(); CodeMirror cmA = null; if (isSideBySide) { cmA = host.getCmFromSide(DisplaySide.A); } CodeMirror cmB = host.getCmFromSide(DisplaySide.B); for (SkippedLine skip : skips) { SkipBar barA = null; SkipBar barB = newSkipBar(cmB, DisplaySide.B, skip); skipBars.add(barB); if (isSideBySide) { barA = newSkipBar(cmA, DisplaySide.A, skip); SkipBar.link(barA, barB); skipBars.add(barA); } if (skip.getStartA() == 0 || skip.getStartB() == 0) { if (isSideBySide) { barA.upArrow.setVisible(false); } barB.upArrow.setVisible(false); setLine0(barB); } else if (skip.getStartA() + skip.getSize() == lineA || skip.getStartB() + skip.getSize() == lineB) { if (isSideBySide) { barA.downArrow.setVisible(false); } barB.downArrow.setVisible(false); } } } } private SkipBar newSkipBar(CodeMirror cm, DisplaySide side, SkippedLine skip) { int start = host.getCmLine(side == DisplaySide.A ? skip.getStartA() : skip.getStartB(), side); int end = start + skip.getSize() - 1; SkipBar bar = new SkipBar(this, cm); host.getDiffTable().add(bar); bar.collapse(start, end, true); return bar; } void ensureFirstLineIsVisible() { if (line0 != null) { line0.expandBefore(1); line0 = null; } } void removeAll() { if (!skipBars.isEmpty()) { for (SkipBar bar : skipBars) { bar.expandSideAll(); } line0 = null; } } void remove(SkipBar a, SkipBar b) { skipBars.remove(a); skipBars.remove(b); if (getLine0() == a || getLine0() == b) { setLine0(null); } } SkipBar getLine0() { return line0; } void setLine0(SkipBar bar) { line0 = bar; } }