DScintilla, code folding not working for me
Frage
I have this code, to initialize Scintilla with xml lexer:
procedure TfrmWeMain.DScintilla1MarginClick(ASender: TObject; AModifiers,
APosition, AMargin: Integer);
var line_number:integer;
begin
line_number:= (ASender as TDScintilla).SendEditor(SCI_LINEFROMPOSITION, APosition, 0);
case AMargin of
1:
begin
(ASender as TDScintilla).SendEditor(SCI_TOGGLEFOLD, line_number, 0);
end
end;
end;
procedure TfrmWeMain.addDocument(filename:string);
var frmEditor:tFrameEditor;
ts:TTabSheet;
procedure setColors(lang:integer;fore:integer;const back:tcolor=clWindow;
const bold:boolean=false; const italic:boolean=false;
const underline:boolean=false; const font:string='Courier New';
const size:integer=10);
begin
frmEditor.sci.StyleSetBack(lang,colortorgb(back));
frmEditor.sci.StyleSetFore(lang,colortorgb(fore));
frmEditor.sci.StyleSetFont(lang,font);
frmEditor.sci.StyleSetBold(lang,bold);
frmEditor.sci.StyleSetItalic(lang,italic);
frmEditor.sci.StyleSetUnderline(lang,underline);
frmEditor.sci.StyleSetSize(lang,size);
end;
procedure setFolding;
begin
frmEditor.sci.SetMarginTypeN(1,0);
frmEditor.sci.SetMarginTypeN(1,SC_MARGIN_SYMBOL);
frmEditor.sci.SetMarginMaskN(1,SC_MASK_FOLDERS);
frmEditor.sci.SetMarginWidthN(0,40);
frmEditor.sci.SetMarginWidthN(1,20);
frmEditor.sci.SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDER, SC_MARK_PLUS);
frmEditor.sci.SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS);
frmEditor.sci.SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY);
frmEditor.sci.SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY);
frmEditor.sci.SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY);
frmEditor.sci.SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY);
frmEditor.sci.SendEditor(SCI_MARKERDEFINE, SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY);
frmEditor.sci.SendEditor(SCI_SETFOLDFLAGS, 16, 0); // 16 Draw line below if not expanded
frmEditor.sci.OnMarginClick:=DScintilla1MarginClick;
frmeditor.sci.StartStyling(0,0);
end;
begin
///...
frmEditor.sci.SetLexer(SCLEX_XML);
frmEditor.sci.SetCodePage(CP_UTF8);
setColors(SCE_H_DEFAULT,clBlack);
setColors(SCE_H_TAG,clPurple,clWindow,true);
setColors(SCE_H_TAGUNKNOWN,clRed);
setColors(SCE_H_ATTRIBUTE,clNavy);
setColors(SCE_H_ATTRIBUTEUNKNOWN,clRed);
setColors(SCE_H_NUMBER,clBlue);
setColors(SCE_H_DOUBLESTRING,clBlue);
setColors(SCE_H_SINGLESTRING,clBlue);
setColors(SCE_H_OTHER,clBlack);
setColors(SCE_H_COMMENT,clTeal);
setColors(SCE_H_ENTITY,clPurple);
setColors(SCE_H_TAGEND,clPurple);
setColors(SCE_H_CDATA,clTeal);
setFolding;
///...
end;
See the setFolding part of the code, it's that where the folding should get in motion, but it doesn't. I can't see the fold markers, neither the folding itself works.
I need to know what i am missing here, or what i am doing wrong. Code snippets in Delphi, C++, C# or pseudocode are welcome
Lösung
Here you have the folding example for XML. You were quite close to get it to work, but you missed to set 2 important details, enable folding globally and for your language (see here for fold.html folding property for XML) and after that enable fold margin to be sensitive for mouse clicks, what actually enables the OnMarginClick event to be fired (see here).
For this example I've avoided to use the SendEditor messaging and used the full power of the DScintilla wrapper.
uses
DScintillaTypes;
const
MARGIN_LINE_NUMBERS = 0;
MARGIN_CODE_FOLDING = 1;
procedure TForm1.DScintilla1MarginClick(ASender: TObject; AModifiers,
APosition, AMargin: Integer);
var
Line: Integer;
begin
Line := DScintilla1.LineFromPosition(APosition);
if AMargin = MARGIN_CODE_FOLDING then
DScintilla1.ToggleFold(Line);
end;
procedure TForm1.FormCreate(Sender: TObject);
procedure SetColors(const Style: Integer; const Fore: Integer;
const Back: TColor = clWindow; const Bold: Boolean = False;
const Italic: Boolean = False; const Underline: Boolean = False;
const Font: string = 'Courier New'; const Size: Integer = 10);
begin
DScintilla1.StyleSetBack(Style, ColorToRGB(Back));
DScintilla1.StyleSetFore(Style, ColorToRGB(Fore));
DScintilla1.StyleSetFont(Style, Font);
DScintilla1.StyleSetSize(Style, Size);
DScintilla1.StyleSetBold(Style, Bold);
DScintilla1.StyleSetItalic(Style, Italic);
DScintilla1.StyleSetUnderline(Style, Underline);
end;
begin
DScintilla1.SetLexer(SCLEX_XML);
DScintilla1.SetCodePage(CP_UTF8);
// this is very important and enables the folding globally
// and then the language specific, see [1] for details
DScintilla1.SetProperty('fold', '1');
DScintilla1.SetProperty('fold.html', '1');
// I used here constant placeholders, for line numbering
// margin it's the MARGIN_LINE_NUMBERS and for code folding
// margin it's the MARGIN_CODE_FOLDING constant
DScintilla1.SetMarginWidthN(MARGIN_CODE_FOLDING, 0);
DScintilla1.SetMarginTypeN(MARGIN_CODE_FOLDING, SC_MARGIN_SYMBOL);
DScintilla1.SetMarginMaskN(MARGIN_CODE_FOLDING, SC_MASK_FOLDERS);
DScintilla1.SetMarginWidthN(MARGIN_LINE_NUMBERS, 40);
DScintilla1.SetMarginWidthN(MARGIN_CODE_FOLDING, 20);
// markers for code folding
DScintilla1.MarkerDefine(SC_MARKNUM_FOLDER, SC_MARK_PLUS);
DScintilla1.MarkerDefine(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS);
DScintilla1.MarkerDefine(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY);
DScintilla1.MarkerDefine(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY);
DScintilla1.MarkerDefine(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY);
DScintilla1.MarkerDefine(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY);
DScintilla1.MarkerDefine(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY);
// also very important, this will enable the OnMarginClick event
// to fire, if you set the ASensitive parameter to False or omit
// this line, the OnMarginClick will never fire
DScintilla1.SetMarginSensitiveN(MARGIN_CODE_FOLDING, True);
// and some visual settings
SetColors(SCE_H_DEFAULT, clBlack);
SetColors(SCE_H_TAG, clPurple, clWindow, True);
SetColors(SCE_H_TAGUNKNOWN, clRed);
SetColors(SCE_H_ATTRIBUTE, clNavy);
SetColors(SCE_H_ATTRIBUTEUNKNOWN, clRed);
SetColors(SCE_H_NUMBER, clBlue);
SetColors(SCE_H_DOUBLESTRING, clBlue);
SetColors(SCE_H_SINGLESTRING, clBlue);
SetColors(SCE_H_OTHER, clBlack);
SetColors(SCE_H_COMMENT, clTeal);
SetColors(SCE_H_ENTITY, clPurple);
SetColors(SCE_H_TAGEND, clPurple);
SetColors(SCE_H_CDATA, clTeal);
end;
Hope this helps :)