removeAttribution method
void
removeAttribution({
- required Attribution attributionToRemove,
- required int start,
- required int end,
Removes attributionToRemove
between start
and end
, inclusive.
Implementation
void removeAttribution({
required Attribution attributionToRemove,
required int start,
required int end,
}) {
_log.info('Removing attribution $attributionToRemove from $start to $end');
if (start < 0 || start > end) {
throw Exception('removeAttribution() did not satisfy start < 0 and start > end, start: $start, end: $end');
}
if (!hasAttributionsWithin(attributions: {attributionToRemove}, start: start, end: end)) {
_log.fine('No such attribution exists in the given span range');
return;
}
// It's possible that a span we want to remove was started before the
// removal region and/or ended after the removal region. Therefore,
// the first thing we do is cut off those outer spans one unit before
// and/or after the removal region.
//
// Example:
// Starting spans + removal region:
// ---[xxxxx]---[yyyyyy]----
// |-remove-|
//
// Spans after end cap adjustment:
// ---[xx]|xxx]---[yy|[yyy]----
//
// Notice that the above marker structure is illegal.
// That's OK because the illegal configuration is only
// temporary. By the end of this method it will look
// like the following:
//
// Spans after all inner markers are removed:
// ---[xx]--------[yyy]----
final endCapMarkersToInsert = <SpanMarker>{};
// Determine if we need to insert a new end-cap before
// the removal region.
if (hasAttributionAt(start - 1, attribution: attributionToRemove)) {
final markersAtStart = _getMarkerAt(attributionToRemove, start - 1, SpanMarkerType.end);
if (markersAtStart.isEmpty) {
_log.finer('Creating a new "end" marker to appear before the removal range at ${start - 1}');
endCapMarkersToInsert.add(SpanMarker(
attribution: attributionToRemove,
offset: start - 1,
markerType: SpanMarkerType.end,
));
}
}
// Determine if we need to insert a new end-cap after the
// removal region.
if (hasAttributionAt(end + 1, attribution: attributionToRemove)) {
final markersAtEnd = _getMarkerAt(attributionToRemove, end + 1, SpanMarkerType.start);
if (markersAtEnd.isEmpty) {
_log.finer('Creating a new "start" marker to appear after the removal range at ${end + 1}');
endCapMarkersToInsert.add(SpanMarker(
attribution: attributionToRemove,
offset: end + 1,
markerType: SpanMarkerType.start,
));
}
}
// Insert new span end-caps immediately before and after
// the removal region, if needed.
for (final endCapMarker in endCapMarkersToInsert) {
_log.finer('Inserting new cap marker: $endCapMarker');
_insertMarker(endCapMarker);
}
// Now that the end caps have been handled, remove all
// relevant attribution markers between [start, end].
final markersToDelete = _markers
.where((attribution) => attribution.attribution == attributionToRemove)
.where((attribution) => attribution.offset >= start)
.where((attribution) => attribution.offset <= end)
.toList();
_log.finer('removing ${markersToDelete.length} markers between $start and $end');
_markers.removeWhere((element) => markersToDelete.contains(element));
_log.finer('all attributions after:');
_markers.where((element) => element.attribution == attributionToRemove).forEach((element) {
_log.finer(' - $element');
});
}