void (boolean animated) { Editor master = getMaster(); Editor slave = getSlave(); if (master.getDocument().getTextLength() == 0) return; Rectangle viewRect = master.getScrollingModel().getVisibleArea(); int lineHeight = master.getLineHeight(); boolean onlyMajorForward = false; boolean onlyMajorBackward = false; int offset; if (myScrollable.forceSyncVerticalScroll()) { offset = viewRect.y; } else if (myAnchor == null) { int middleY = viewRect.height / 3; int masterOffset = viewRect.y + middleY; int masterVisualLine = master.yToVisualLine(masterOffset); int convertedVisualLine = transferVisualLine(masterVisualLine); int slaveOffset = slave.visualLineToY(convertedVisualLine); int masterOffsetRaw = master.visualLineToY(masterVisualLine); // ensure that anchor lines are in the same phase int correction = (masterOffset - masterOffsetRaw) % lineHeight; offset = slaveOffset - middleY + correction; onlyMajorBackward = correction < lineHeight / 2 && masterVisualLine > 0 && convertedVisualLine == transferVisualLine(masterVisualLine - 1); onlyMajorForward = correction > lineHeight / 2 && convertedVisualLine == transferVisualLine(masterVisualLine + 1); } else { double progress = myAnchor.masterStartOffset == myAnchor.masterEndOffset || viewRect.y == myAnchor.masterEndOffset ? 1 : ((double)(viewRect.y - myAnchor.masterStartOffset)) / (myAnchor.masterEndOffset - myAnchor.masterStartOffset); offset = myAnchor.slaveStartOffset + (int)((myAnchor.slaveEndOffset - myAnchor.slaveStartOffset) * progress); } int deltaHeaderOffset = getHeaderOffset(slave) - getHeaderOffset(master); doScrollVertically(slave, offset + deltaHeaderOffset, animated, onlyMajorForward, onlyMajorBackward); }