How do I delete the first few lines in my TextEditor?

I want my read-only TextEditor to have a limit on the number of lines. When new lines are added to the bottom (I’m using it for logging), I need to see if I’m over the limit, and delete lines from the top if necessary.

What’s the right way to do this?

I thought I’d already given you the answer! :slight_smile:
the simplest way is to use a StringArray for your logging (each entry is a ‘line’), prune early entries as necessary, and dump it to the TextEditor after an async notification.

I did that already, and yes pruning lines from the StringArray is quite simple. But if the TextEditor is up, and it gets full, how do I trim it?

Or are you suggesting that every time a new line appears in the StringArray, I rebuild the entire contents of the TextEditor? I sure hope not!

psh, are you a man or a mouse?

I’ve never had any issues doing it like that, it’s certainly the easiest option :wink: but then whenever I’ve used such a component it’s always been for debugging purposes anyway.

I guess you could use the caret operations to select text at the start and replace with String::empty. That’d require that you store how long the removed strings are though, so you know much to chop off.

If you are really concerned with efficiency though, you’d be using a log viewing component that actually thought in lines rather than a giant string. Perhaps the CodeEditorComponent would be worth experimenting with? From the looks of it, it’d need you to store the log in a CodeDocument. It doesn’t look like CodeEditorComponent currently has a read-only mode yet though - if not, I’m sure it’d be a sensible request.

:smiley:
a special custom control indeed is better than one string in a text editor - scheme.

String text = editor->getText();
for (int i = 0; i < nbLinesToTrim; i++) text = text.fromFirstOccurrenceOf("\n", false, false);
editor->setText(text, whatever_here);

Dude…LOL!!! Come on man…you don’t see the problem here?

String text = editor->getText();

No. String are ref counted so this line doesn’t copy the content.
If you’re in your text editor component, then you change “editor” by “this”.

const String TextEditor::getText() const
{
    String t;
    t.preallocateStorage (getTotalNumChars());
    String::Concatenator concatenator (t);

    for (int i = 0; i < sections.size(); ++i)
        sections.getUnchecked (i)->appendAllText (concatenator);

    return t;
}

Plus if you use setText, you lose all the formatting :frowning:

Sorry to exhume that old thread, but is anybody has already implemented something efficient for that, since those antediluvian ages? It seems a rather usual feature, and i’m surprised to found nothing already done for that nowadays.

After few tests i think i’ll use something like that:

void removeLinesAtStartIfRequired()
{
    if (++lines_ % trimRate_ == 0) {
    //
    text_.setCaretPosition (text_.getTotalNumChars() / 2);
    text_.moveCaretToStartOfLine (false);
    text_.moveCaretToTop (true);
    text_.insertTextAtCaret (juce::String ("...") + juce::newLine);
    //
    }
}

That just delete half of the content every nth lines logged.
It seems a good tradeoff concerning efficiency.
I tried other approaches without (better) success.
Lots of usefull functions are kept private in TextEditor.
Use moveCaretDown from top to the nth lines seems (at first glance) too heavy.
Or even a simplest if preserving lines is not required. :laughing:

void removeLinesAtStartIfRequired()
{
    lines_++;
    
    if (lines_ % trimRate_ == 0) {
    //
    text_.setHighlightedRegion (juce::Range<int> (0, text_.getTotalNumChars() / 2));
    text_.insertTextAtCaret (juce::String ("...") + juce::newLine);
    //
    }
}

Note that i did no benchmarks (nor tests) for now.