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

Make the TextView API more extensible #2680

Closed
LPeter1997 opened this issue May 28, 2023 · 11 comments
Closed

Make the TextView API more extensible #2680

LPeter1997 opened this issue May 28, 2023 · 11 comments

Comments

@LPeter1997
Copy link

Is your feature request related to a problem? Please describe.
Currently TextView only supports syntax highlighting through SetXXXColor(List<System.Rune> line, int idx) APIs, which doesn't even tell us what line we are on. This blocks 2 things in our use-case:

  • Syntax highlighting for languages where tokens can span multiple lines.
  • Highlighting the background of the currently executed statement in a debugger, which needs a line number.

Describe the solution you'd like
Expose all lines and the currently highlighted line index in some way. If the API was SetXXXColor(List<List<Rune>> lines, int lineIndex, int columnIndex), it would be a huge improvement and could technically solve both issues. Tho I understand that this isn't too nice of an API either.

Describe alternatives you've considered
I'm not familiar with other existing APIs that aren't too specific to syntax highlighting, so can't think of any.

@tznind
Copy link
Collaborator

tznind commented May 28, 2023

This feature would be great.

I added the current syntax highlighting a while back but did it with as little modification of the view code as possible (TextView is 4000 lines of code 😱). It currently runs as part of render but I agree the solution is incomplete. One area of complexity is the WordWrapManager.

@BDisp maybe we could add an interface to TextModel that exposes only those public methods an API user needs for evaluating the content more comprehensively than just using Text?

interface ITextModel
{
   int LineCount {get;}
   List<Rune> GetLine(int line);
}

We could let user define syntax highlighting once for the whole ITextModel and then we hold onto that mapping and use it internally in TextView?

So TextModel would become something like:

class TextModel : ITextModel {
    List<List<Rune>> _lines = new List<List<Rune>> ();
    List<List<ColorScheme>> _colors = new List<List<ColorScheme>> ();


	/// <summary>
	/// Updates the colors used to render each rune in the given <paramref name="line"/>
	/// </summary>
	/// <param name="line">Line number in the source text (ignoring wrapping)</param>
	/// <param name="colorsByRune">Color to use for each rune.  Must match the number
	/// of runes on the line (see <see cref="GetLine(int)"/>)</param>
	public void SetTextColors (int line, IEnumerable<ColorScheme> colorsByRune)
	{
		[...]
	}

	[...]
}

It would be up to the user to register for TextChanged events, diff the old and new text and reassign colors for any changed regions?

We could make a helper class if that was onerous or had subtlties?

Or we could switch TextModel to using Cell instead of Rune for the data model. That way we wouldn't have 2 lists that could get out of sync.

@BDisp
Copy link
Collaborator

BDisp commented May 28, 2023

Or we could switch TextModel to using Cell instead of Rune for the data model. That way we wouldn't have 2 lists that could get out of sync.

This is a great idea. I'll explore it. Thanks.

@tig
Copy link
Collaborator

tig commented May 28, 2023

Cool!

As you dig into this @BDisp know I'm conflicted on Cell.

Should it hold a list of Runes? Or a string?

For ConsoleDriver all that's really needed is up to two Runes (there are no known combining marks that can't reduce down to two code points).

I also have considered the possibility that it could provide a place where keeping track of "to my left is a low surrogate" or "to my right is a high surrogate".

Please feel free to invent here!

@BDisp
Copy link
Collaborator

BDisp commented May 28, 2023

Cool!

As you dig into this @BDisp know I'm conflicted on Cell.

Should it hold a list of Runes? Or a string?

I'm considering as it is, although it was better the Rune wasn't nullable, but I'm workaround that. So it's better to be only a Rune. If two code points is needed then we use two Cell. That way is much more easy to manage with TextModel.

For ConsoleDriver all that's really needed is up to two Runes (there are no known combining marks that can't reduce down to two code points).

Alright we also are dependent on what each driver can do with that.

I also have considered the possibility that it could provide a place where keeping track of "to my left is a low surrogate" or "to my right is a high surrogate".

Isn't it the opposite?

Please feel free to invent here!

For now I'm leaving the Cell class as is and adapt all the code that use TextModel to handle with Cell.

@tig
Copy link
Collaborator

tig commented May 28, 2023

To be clear, I WILL be changing cell to use either List of Runes or a string...

@BDisp
Copy link
Collaborator

BDisp commented May 28, 2023

To be clear, I WILL be changing cell to use either List of Runes or a string...

Well that is now complicating my work :-)
TextModel works better with Rune. With a List I can managed it but with strings the code will be much more complicate. I'm really think to create a dedicate type for TextModel. I'm not advance more with this without we clarify what we really going to do.

@tznind
Copy link
Collaborator

tznind commented May 28, 2023

To be clear, I WILL be changing cell to use either List of Runes or a string...

Well that is now complicating my work :-) TextModel works better with Rune. With a List I can managed it but with strings the code will be much more complicate. I'm really think to create a dedicate type for TextModel. I'm not advance more with this without we clarify what we really going to do.

I think its ok to make a new Type for TextModel. Its a 2 property class so no big deal to just have TextModelCell or something if it makes things easier.

Thanks for taking this work on @BDisp I think its gonna be pretty awesome.

@BDisp
Copy link
Collaborator

BDisp commented May 28, 2023

I think its ok to make a new Type for TextModel. Its a 2 property class so no big deal to just have TextModelCell or something if it makes things easier.

Thanks for taking this work on @BDisp I think its gonna be pretty awesome.

I think so too. I'll use RuneCell. That's ok?

@tznind
Copy link
Collaborator

tznind commented May 28, 2023

I think so too. I'll use RuneCell. That's ok?

Sure that works. If its just for TextModel / TextView though you could go with TextViewCell or TextModelCell to avoid confusion with the existing Cell class?

Its up to you though.

@BDisp
Copy link
Collaborator

BDisp commented May 28, 2023

Sure that works. If its just for TextModel / TextView though you could go with TextViewCell or TextModelCell to avoid confusion with the existing Cell class?

Its up to you though.

Well, it will affect others views than TextView, like TextField, DateField and TimeField, besides RuneExtensions and StringExtensions. And a lot of others class. But I like the name RuneCell :-)

@BDisp
Copy link
Collaborator

BDisp commented May 29, 2023

Done. I think I've to add some more methods, like to get line at some index, but please review and then I'll add the missing methods. Thanks.

tig pushed a commit that referenced this issue Jul 6, 2023
* Fixes #2680. Make the TextView API more extensible.

* Remove unnecessary using.

* Add GetLine method.

* Change RuneCell Attribute property to ColorScheme property.

* Add LoadRuneCells method and unit test.

* Add helper method to set all the Colors.ColorSchemes with the same attribute.

* Change RuneCell to class.

* Add IEquatable<RuneCell> interface.

* Fix unit test.

* Still fixing unit test.

* Fixes #2688. ReadOnly TextView's broken scrolling after version update.

* keyModifiers must be reset after key up was been processed.

* Trying fix server unit test error.

* Prevents throw an exception if RuneCell is null.

* Still trying fix this unit test.

* Cleaning code.

* Fix when the RuneCell is null.

* Fix throwing an exception if current column position is greater than the line length.

* Fixes #2689. Autocomplete doesn't popup after typing the first character.

* Fix Used on TextField.

* Always use the original ColorScheme if RuneCell.ColorScheme is null.

* Fix Used on TextView.

* Add RuneCellEventArgs and draw colors events.

* Add two more samples to the scenario.

* Fix a bug which was causing unit tests with ColorScheme fail.

* Fix a issue when WordWrap is true by always loading the old text.

* Improves debugging in RuneCell.

* WordWrap is now preserving the ColorScheme of the unwrapped lines.

* Simplifying unit test.

* Ensures the foreground and background colors are never the same if Used is false.

* Remove nullable from the parameter.

* Merge syntax highlighting of quotes and keywords together

* Add IdxRow property into the RuneCellEventArgs.

* Fix pos calculation on windows
(where newline in Text is \r\n not \n)

* Fix events not being cleared when toggling samples.

* Change Undo and Redo to a public method.

* Changes some methods names to be more explicit.

* Call OnContentsChanged on needed methods and fix some more bugs.

* Adds InheritsPreviousColorScheme to allow LoadRuneCells uses personalized color schemes.

* Serializes and deserializes RuneCell to a .rce extension file.

* Prevents throwing if column is bigger than the line.

* Avoids create a color attribute without one of the foreground or background values. In Linux using -1 throws an exception.

* Replace SetAllAttributesBasedOn method with a ColorScheme constructor.

* Move RuneCell string extensions to TextView.cs

* Reverted parameter name from cell to rune.

* Change Row to UnwrappedPosition which provide the real unwrapped text position within the Col.

* Add brackets to Undo and Redo methods.

* Replace all the LoadXXX with Load and rely on the param type to differentiate.

* Open a file inside a using.

* Proves that the events run twice for WordWrap disabled and the enabled.

* Remove GetColumns extension for RuneCell.

* Add braces to Undo an Redo.

* Change comment.

* Add braces.

* Delete remarks tag.

* Explaining used color and ProcessInheritsPreviousColorScheme.

* Fix comment.

* Created a RuneCellTests.cs file.

* Rename to StringToLinesOfRuneCells.

* Make ToRuneCells private.

---------

Co-authored-by: Thomas <tznind@dundee.ac.uk>
Co-authored-by: Thomas Nind <31306100+tznind@users.noreply.github.com>
@tig tig closed this as completed Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: ✅ Done
Development

No branches or pull requests

4 participants