[SuperEditor][SuperReader] - Custom underline style configuration (Resolves #2675) #2677
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
[SuperEditor][SuperReader] - Custom underline style configuration (Resolves #2675)
Text can now be attributed for a custom underline, and that custom underline is painted by
SuperEditor
andSuperReader
.The first step is to attribute some text with a
CustomUnderlineAttribution
. This attribution includes atype
which is aString
that can be anything. Thetype
is interpreted by the style system, so as long as thetype
maps to an underline style, it will be honored. An unknown type will paint a straight black underline.Each
TextComponentViewModel
has the stylesheet applied to it inapplyStyles()
. Each text view model now looks for a collection of underline styles:customUnderlineStyles = styles[Styles.customUnderlineStyles];
. EachTextComponentViewModel
holds on to those styles.A new style phase called
CustomUnderlineStyler
inspects eachTextComponentViewModel
and looks forCustomUnderlineAttribution
s in the text. If it finds any, then theCustomUnderlineStyler
adds underlines to theTextComponentViewModel
for each attribution.After each view model runs
applyStyles()
and after theCustomUnderlineStyler
parses the underlines out of the text, eachTextComponentViewModel
has enough information to create a list of underline styles for the text in the node. The method for this already existed before this PR - it's calledcreateUnderlines()
. That method now also creates these new custom underlines in addition to the existing composing region, spelling, and grammar underlines. ThecreateUnderlines()
method is called when the component is configured with the view model, e.g., whenParagraphComponent
is created from the view model.This PR also adds an
offset
property to the existing underline styles so that the underlines can be pushed up/down from their natural position.Unrelated Changes
As I tried to add a new property to all text component view models, it became clear that it's tedious and error prone to maintain our approach to mixing in
TextComponentViewModel
and implementingcopy()
,==
, andhashCode
. This requires replicating many lines per implementation and it's easy to miss one.I refactored these relationships to significantly reduce tedious boilerplate.
Previously a call to
copy()
would create a new view model by passing every relevant property into its constructor. This required every text component to repeat all of these properties in the call to their constructors. The new approach in this PR is to leverage mutability, and let the mixin mutate all the properties that it wants. In other words, classes likeParagraphComponentViewModel
andListItemComponentViewModel
now delegate toTextComponentViewModel
to copy all the properties fromTextComponentViewModel
. As a result, we can implement new properties onTextComponentViewModel
without altering any class that mixes inTextComponentViewModel
.A similar change was made to help with implementing
==
andhashCode
via delegation toTextComponentViewModel
.Demo