// 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 SideBySide2}. */ class SkipManager { private final SideBySide2 host; private final CommentManager commentManager; private Set<SkipBar> skipBars; private SkipBar line0; SkipManager(SideBySide2 host, CommentManager commentManager) { this.host = host; this.commentManager = commentManager; } OverviewBar getOverviewBar() { return host.diffTable.overview; } 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(); } getOverviewBar().refresh(); 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; } }