Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Highlight a particular line via CSS within a multi-line paragraph #611

Closed
garybentley opened this issue Oct 13, 2017 · 10 comments
Closed

Highlight a particular line via CSS within a multi-line paragraph #611

garybentley opened this issue Oct 13, 2017 · 10 comments

Comments

@garybentley
Copy link

So the style and psuedo-class:

.paragraph-box:has-caret
{

}

allows you to style a paragraph which works well when a paragraph is also just the entire line but in the case where you have a paragraph spanning/wrapping onto multiple lines within the view it doesn't really give you what you want. It will style the entire paragraph rather than a line within it.

Thus if I have a single paragraph:

This is the first part of a long paragraph ...
We imagine here that this is still part of the same paragraph. ...
And this is the final line of the single paragraph.

If I want to highlight the line starting "We imagine..." what is the best way to do that? I should add here that the caret will be somewhere along that line in the view.

That is, I want to highlight the current line that the user is typing on (they will be typing continuous prose). As the caret moves down the highlighted line should shift.

Do I need to add an external overlay (a highlight region as part of a StackPane) or is there a way within GenericStyledArea to do it?

@JordanMartinez JordanMartinez changed the title What would be the best way to highlight a particular line within a paragraph? Highlight a particular line via CSS within a multi-line paragraph Oct 13, 2017
@JordanMartinez
Copy link
Contributor

Currently, no, there is not a way to do that. However, we could add another pseudo class that would activate when the caret is on that specific line.
I'm also not going to include this in the 0.7-M7 release. It'll have to come later than that.

@garybentley
Copy link
Author

Could you point me in the general direction of how I could add that myself? I'm happy to add these features myself and then make them available as PRs if needed. I just need the best place to start looking.

@JordanMartinez
Copy link
Contributor

It'll need to be added in ParagraphText as a separate Path object (similar to what we do with selection/caret shape). You'd need to use a method that would determine which line the caret is on, create a Path object that is made using the range bounds for that line, and add that Path object to the first item in the getChildren() list so that it appears in the background rather than the foreground. Additionally, this node would need to be updated every time layoutChildren() is called in case the user scrolled.

@garybentley
Copy link
Author

Thanks. That sets me in the right direction. I'm thinking here that perhaps it would be better to look at this in a broader scope. That is, to allow for any number of "selections" or highlights to be made in an area. For example, to allow for multiple search results to be highlighted or perhaps keywords highlighted.

So if I create a TrackedIndexRange object (for example, with tracked start and end positions) what would be the best way to keep the Paths updated in the ParagraphText objects as the offsets change?

For example if I have the paragraphs:

1 | This is the first line.
2 | This is the second line.

and then want to add a highlight between 8 and 32 (the start of the first "the" and the start of the second "the"), I will have to add two paths, one for each ParagraphText with the relevant IndexRange for each. Then if I insert characters between offsets 8 and 32 or add new lines then I would need to modify the Paths. The question is, what is the best way to manage the changes to the paths and what should I trigger off of?

@JordanMartinez
Copy link
Contributor

Thanks. That sets me in the right direction. I'm thinking here that perhaps it would be better to look at this in a broader scope. That is, to allow for any number of "selections" or highlights to be made in an area. For example, to allow for multiple search results to be highlighted or perhaps keywords highlighted.

That sounds like #222

@garybentley
Copy link
Author

It sounds very similar. I'm going to have a go at implementing the feature. Any suggestions on the best way to manage moving the Path selections around the ParagraphText nodes? I was thinking of just listening for viewport and text changes and adding/removing the selections as appropriate.

@JordanMartinez
Copy link
Contributor

JordanMartinez commented Oct 20, 2017

Mm.... this gets a bit complicated.

Styling the individual lines of a multi-line paragraph has no relation whatsoever to the text (or segment)'s style. After realizing this, one might say it should go into the paragraph style. However, I'm not sure this is the best route either.

There are a number of problems that have to be resolved:

  • What happens when you style Line 2 in a 5-line paragraph and then the user narrows/widens the viewport, causing the paragraph to now span across more or less lines? In other words, is Line 2's styling absolute (as long as a second line is shown, no matter how long/short its text is, it should keep its style) or relative (if a change in viewport occurs, things are set back to no styling; if one wants it after this point, they have to reapply it)
  • How does the code know which line is the line that should be styled in a multi-line paragraph? In other words...
    • Do we use pseudo classes for a paragraph's style (e.g. .paragraph:line-1 {} and .paragraph:line-2 {})? Probably not since it can't be used for individual paragraphs.
    • Do we use IDs (e.g. .par-one-line-one {})? Maybe...?
    • Do we hard-code it somehow (e.g. public final <LS> area.styleLine(int parIdx, int lineIdx, Consumer<Path> applyStyle)) (Note: this would require adding another generic to GenericStyledArea)
  • How/Where are the styles stored? In EditableStyledDocument? (probably yes) In Paragraph? (probably no)
  • When the viewport changes (scrolling up/down or narrowing/widening), how should that trigger the layout process, so that the Path objects get updated and we don't create memory leaks?

@garybentley
Copy link
Author

I think most of the work has been done in the SelectionImpl class. With another class, say "Highlight" that would encapsulate a Selection instance and a style (StyleableObjectProperty).

The highlight, as I'm talking about would not be for a line, but for an index range, a from/to combination. The caret line highlighting would be a special case where the from/to would be recalculated when the viewport changes size. As part of #613 I'm looking into querying the virtual flow to determine what line(s) are currently visible in the viewport.

Lines 1285-1291 of GenericStyledArea show a potential binding mechanism. I'll look into using something similar for the selections although I'll need to detect when the selection is no longer valid for the paragraph and remove it to prevent the potential memory leak.

Once I have a working prototype I'll let you know.

@JordanMartinez
Copy link
Contributor

Mm.. So how is this different from #222? It seems you want a SelectionImpl instance that would use a different style class (perhaps "highlight") and you want to be able to add/remove multiple instances to/from the area. Would this feature need to be built on top of something that resolves #222?

@garybentley
Copy link
Author

Yes it looks almost the same to what I'm looking for. Sorry for the delay, had a busy few days. I'll bear those issues in mind when implementing my prototype.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants