jacobslusser / ScintillaNET

A Windows Forms control, wrapper, and bindings for the Scintilla text editor.
MIT License
963 stars 243 forks source link

ScintillaNet Folding Question #328

Open TimMakins opened 7 years ago

TimMakins commented 7 years ago

I am trying to write a minimum example of Scintilla folding. The program has a form with 2 textboxes that supply integers for the line number to start folding, and the number of lines to fold. There are also 2 buttons: 'Add Folding' that initiates the folding, and 'Clear Folding' that removes that folding. The 'Add Folding' works fine, and lets me add a number of small folds, but the 'Clear Folding' seems to clog the system up after a few attempts, and does not always show the folding line descenders when adding folding a second time. I assume that I am trying to clear my folding in the wrong way, but much searching has not shown me how I should be doing it. I would therefore be very grateful if you could point out my errors:

`Imports ScintillaNET Public Class Form1

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    Dim sci As New Scintilla
    With sci
        .Location = New Point(0, 0)
        .Name = "sci"
        .Size = New Size(500, 400)
        .Margins(2).Width = 20
        .Margins(2).Type = MarginType.Symbol
        .Margins(2).Mask = Marker.MaskFolders
        .Margins(2).Sensitive = True
        ' Set colors for all folding markers
        For i As Integer = Marker.FolderEnd To Marker.FolderOpen
            .Markers(i).SetForeColor(SystemColors.Control)
            .Markers(i).SetBackColor(SystemColors.ControlDark)
        Next
        ' Configure folding markers with respective symbols
        .Markers(Marker.FolderEnd).Symbol = MarkerSymbol.BoxPlusConnected
        .Markers(Marker.FolderOpenMid).Symbol = MarkerSymbol.BoxMinusConnected
        .Markers(Marker.FolderMidTail).Symbol = MarkerSymbol.TCorner
        .Markers(Marker.FolderTail).Symbol = MarkerSymbol.LCorner
        .Markers(Marker.FolderSub).Symbol = MarkerSymbol.VLine
        .Markers(Marker.Folder).Symbol = MarkerSymbol.BoxPlus
        .Markers(Marker.FolderOpen).Symbol = MarkerSymbol.BoxMinus
        .Lexer = Lexer.Container
        ' Add some test lines
        For i As Integer = 1 To 28
            .AddText("Line " & i & vbCrLf)
        Next
        AddHandler .MarginClick, AddressOf sci_MarginClick
    End With
    Controls.Add(sci)
End Sub

Private Sub sci_MarginClick(sender As Object, e As MarginClickEventArgs)
    Dim sci As Scintilla = CType(sender, Scintilla)
    ' Toggle the fold when clicking
    Dim line = sci.LineFromPosition(e.Position)
    sci.Lines(line).ToggleFold()
End Sub

Private Sub btnAddFolding_Click(sender As Object, e As EventArgs) Handles btnAddFolding.Click
    ' Add Folding
    Dim sci As Scintilla = CType(Controls("sci"), Scintilla)
    Dim foldStart As Integer = CInt(tbxStartFolding.Text) - 1
    Dim foldLength As Integer = CInt(tbxNoOfLines.Text) - 1
    sci.Lines(foldStart).FoldLevelFlags = FoldLevelFlags.Header
    Dim foldLevel As Integer = sci.Lines(foldStart).FoldLevel
    foldLevel += 1
    For i As Integer = 1 To foldLength
        sci.Lines(foldStart + i).FoldLevel = foldLevel
    Next
    foldLevel -= 1
End Sub

Private Sub btnClearfolding_Click(sender As Object, e As EventArgs) Handles btnClearfolding.Click
    ' Clear Folding
    Dim sci As Scintilla = CType(Controls("sci"), Scintilla)
    Dim foldStart As Integer = CInt(tbxStartFolding.Text) - 1
    Dim foldLength As Integer = CInt(tbxNoOfLines.Text) - 1
    Dim foldLevel As Integer = sci.Lines(foldStart).FoldLevel
    For i As Integer = 1 To foldLength
        sci.Lines(foldStart + i).FoldLevel = 0
    Next
End Sub

End Class`

jacobslusser commented 7 years ago

In issue #307 I give a pretty good example of how to do folding. In your case, it looks to me like you are resetting the fold value to 0 when clearing--which could be the problem. The default value of a fold is 1024.

EDIT: it also looks like you're not resetting the FoldLevelFlags?

TimMakins commented 7 years ago

Thanks for replying to my question. In your #307 example there is no mention of resetting the FoldLevelFlags either. How should I reset them? Some information on FoldLeveLflags in general would be very helpful for all of us, I am sure.

Kind Regards, Tim

Miki101 commented 6 years ago

Hi, I found that setting the FoldLevelFlags to 0 is the same thing as resetting the flag. Here's some C# code that I've been tinkering with.

    private void AddFoldRegion(int StartLine,int EndLine,int CurrentLevel)
    {
    int Start = StartLine,End = EndLine;

        if (StartLine > EndLine)
        {
            Start = EndLine;
            End = StartLine;
        }
        TextEditor.Lines[Start].FoldLevelFlags = FoldLevelFlags.Header;
        TextEditor.Lines[Start].FoldLevel = CurrentLevel;
        for(int i = Start + 1;i < End;++i)
        {
            TextEditor.Lines[i].FoldLevel = TextEditor.Lines[Start].FoldLevel + 1;
            TextEditor.Lines[i].FoldLevelFlags = FoldLevelFlags.White;
        }
        TextEditor.Lines[End].FoldLevel = TextEditor.Lines[Start].FoldLevel + 1;
    }
    private void RemoveFoldRegion(int StartLine,int EndLine,int CurrentLevel)
    {
    int Start = StartLine,End = EndLine;

        if (StartLine > EndLine)
        {
            Start = EndLine;
            End = StartLine;
        }
        TextEditor.Lines[Start].FoldLevelFlags = 0;
        TextEditor.Lines[Start].FoldLevel = CurrentLevel;
        for(int i = Start + 1;i < End;++i)
        {
            TextEditor.Lines[i].FoldLevel = TextEditor.Lines[Start].FoldLevel;
            TextEditor.Lines[i].FoldLevelFlags = 0;
        }
        TextEditor.Lines[End].FoldLevel = TextEditor.Lines[Start].FoldLevel;
    }

Hopefully, this will be of some help to you.

Deepchand-Calmove commented 3 years ago

Hi, I found that setting the FoldLevelFlags to 0 is the same thing as resetting the flag. Here's some C# code that I've been tinkering with.

  private void AddFoldRegion(int StartLine,int EndLine,int CurrentLevel)
  {
  int Start = StartLine,End = EndLine;

      if (StartLine > EndLine)
      {
          Start = EndLine;
          End = StartLine;
      }
      TextEditor.Lines[Start].FoldLevelFlags = FoldLevelFlags.Header;
      TextEditor.Lines[Start].FoldLevel = CurrentLevel;
      for(int i = Start + 1;i < End;++i)
      {
          TextEditor.Lines[i].FoldLevel = TextEditor.Lines[Start].FoldLevel + 1;
          TextEditor.Lines[i].FoldLevelFlags = FoldLevelFlags.White;
      }
      TextEditor.Lines[End].FoldLevel = TextEditor.Lines[Start].FoldLevel + 1;
  }
  private void RemoveFoldRegion(int StartLine,int EndLine,int CurrentLevel)
  {
  int Start = StartLine,End = EndLine;

      if (StartLine > EndLine)
      {
          Start = EndLine;
          End = StartLine;
      }
      TextEditor.Lines[Start].FoldLevelFlags = 0;
      TextEditor.Lines[Start].FoldLevel = CurrentLevel;
      for(int i = Start + 1;i < End;++i)
      {
          TextEditor.Lines[i].FoldLevel = TextEditor.Lines[Start].FoldLevel;
          TextEditor.Lines[i].FoldLevelFlags = 0;
      }
      TextEditor.Lines[End].FoldLevel = TextEditor.Lines[Start].FoldLevel;
  }

Hopefully, this will be of some help to you.

Well it was very much helpful to me. :) I implemented Alt+0 to fold all lines just like in notepad++. Thanks Miki for your piece of code.