SynEdit Folding: Improved Pop-up-Menu on fold-gutter => replace normal popup.

git-svn-id: trunk@19516 -
This commit is contained in:
martin 2009-04-19 17:11:02 +00:00
parent 3c56977f01
commit 6a6c84d56b
4 changed files with 73 additions and 38 deletions

View File

@ -69,7 +69,7 @@ uses
{$ELSE} {$ELSE}
Windows, Windows,
{$ENDIF} {$ENDIF}
SysUtils, Classes, Messages, Controls, Graphics, Forms, StdCtrls, ExtCtrls, SysUtils, Classes, Messages, Controls, Graphics, Forms, StdCtrls, ExtCtrls, Menus,
{$IFDEF SYN_MBCSSUPPORT} {$IFDEF SYN_MBCSSUPPORT}
Imm, Imm,
{$ENDIF} {$ENDIF}
@ -630,6 +630,7 @@ type
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
override; override;
function GetPopupMenu: TPopupMenu; override;
procedure NotifyHookedCommandHandlers(AfterProcessing: boolean; procedure NotifyHookedCommandHandlers(AfterProcessing: boolean;
var Command: TSynEditorCommand; var Command: TSynEditorCommand;
var AChar: {$IFDEF SYN_LAZARUS}TUTF8Char{$ELSE}Char{$ENDIF}; var AChar: {$IFDEF SYN_LAZARUS}TUTF8Char{$ELSE}Char{$ENDIF};
@ -2644,6 +2645,13 @@ begin
//DebugLn('TCustomSynEdit.MouseUp END Mouse=',X,',',Y,' Caret=',CaretX,',',CaretY,', BlockBegin=',BlockBegin.X,',',BlockBegin.Y,' BlockEnd=',BlockEnd.X,',',BlockEnd.Y); //DebugLn('TCustomSynEdit.MouseUp END Mouse=',X,',',Y,' Caret=',CaretX,',',CaretY,', BlockBegin=',BlockBegin.X,',',BlockBegin.Y,' BlockEnd=',BlockEnd.X,',',BlockEnd.Y);
end; end;
function TCustomSynEdit.GetPopupMenu: TPopupMenu;
begin
if (sfGutterClick in fStateFlags) and FGutter.HasCustomPopupMenu(Result) then
exit;
Result := inherited GetPopupMenu;
end;
procedure TCustomSynEdit.Paint; procedure TCustomSynEdit.Paint;
var var
rcClip, rcDraw: TRect; rcClip, rcDraw: TRect;

View File

@ -5,7 +5,7 @@ unit SynGutter;
interface interface
uses uses
Classes, Controls, Graphics, LCLType, LCLIntf, Classes, Controls, Graphics, LCLType, LCLIntf, Menus,
SynEditMarks, SynEditMiscClasses, SynEditMiscProcs, SynEditFoldedView, SynEditMarks, SynEditMiscClasses, SynEditMiscProcs, SynEditFoldedView,
SynTextDrawer, SynGutterBase, SynGutterLineNumber, SynGutterCodeFolding, SynTextDrawer, SynGutterBase, SynGutterLineNumber, SynGutterCodeFolding,
SynGutterMarks, SynGutterChanges; SynGutterMarks, SynGutterChanges;
@ -48,6 +48,7 @@ type
procedure Assign(Source: TPersistent); override; procedure Assign(Source: TPersistent); override;
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer);
function RealGutterWidth(CharWidth: integer): integer; function RealGutterWidth(CharWidth: integer): integer;
function HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MouseMove(Shift: TShiftState; X, Y: Integer); procedure MouseMove(Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
@ -303,6 +304,11 @@ begin
TSynGutterLineNumber(Parts.ByClass[TSynGutterLineNumber, i]).AutoSizeDigitCount(LinesCount); TSynGutterLineNumber(Parts.ByClass[TSynGutterLineNumber, i]).AutoSizeDigitCount(LinesCount);
end; end;
function TSynGutter.HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean;
begin
Result := Parts[FMouseDownPart].HasCustomPopupMenu(PopMenu);
end;
procedure TSynGutter.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TSynGutter.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin begin
FMouseDownPart := PixelToPartIndex(X); FMouseDownPart := PixelToPartIndex(X);

View File

@ -5,7 +5,7 @@ unit SynGutterBase;
interface interface
uses uses
Classes, SysUtils, Graphics, Controls, SynEditMarks, Classes, SysUtils, Graphics, Controls, Menus, SynEditMarks,
SynEditMiscClasses, SynEditFoldedView, SynTextDrawer; SynEditMiscClasses, SynEditFoldedView, SynTextDrawer;
type type
@ -108,6 +108,7 @@ type
public public
function RealGutterWidth(CharWidth: integer): integer; virtual; abstract; function RealGutterWidth(CharWidth: integer): integer; virtual; abstract;
// X/Y are relative to the gutter, not the gutter part // X/Y are relative to the gutter, not the gutter part
function HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean; virtual;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); virtual; procedure MouseMove(Shift: TShiftState; X, Y: Integer); virtual;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
@ -290,6 +291,11 @@ begin
inherited; inherited;
end; end;
function TSynGutterPartBase.HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean;
begin
Result := False;
end;
procedure TSynGutterPartBase.MouseDown(Button: TMouseButton; Shift: TShiftState; X, procedure TSynGutterPartBase.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer); Y: Integer);
begin begin

View File

@ -34,6 +34,8 @@ type
TSynGutterCodeFolding = class(TSynGutterPartBase) TSynGutterCodeFolding = class(TSynGutterPartBase)
private private
FClickDone: Boolean;
FClickLine: Integer;
FFoldView: TSynEditFoldedView; FFoldView: TSynEditFoldedView;
FExpandedClickConf, FExpandedClickConf,
FCollapsedClickConf: TSynGutterFoldClickConfList; FCollapsedClickConf: TSynGutterFoldClickConfList;
@ -49,6 +51,7 @@ type
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer);
override; override;
function RealGutterWidth(CharWidth: integer): integer; override; function RealGutterWidth(CharWidth: integer): integer; override;
function HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure DoOnGutterClick(X, Y: integer); override; procedure DoOnGutterClick(X, Y: integer); override;
@ -144,24 +147,21 @@ end;
procedure TSynGutterCodeFolding.MouseDown(Button: TMouseButton; Shift: TShiftState; X, procedure TSynGutterCodeFolding.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer); Y: Integer);
var var
ClickDone: Boolean; line: Integer;
m: TMenuItem;
line, i, c: Integer;
inf: TFoldViewNodeInfo;
s, s2: String;
function isClick(conf : TSynGutterFoldClickConf): Boolean; function isClick(conf : TSynGutterFoldClickConf): Boolean;
begin begin
if ClickDone then exit(False); if FClickDone then exit(False);
Result := ( conf.Enabled and (Button = conf.Button) and Result := ( conf.Enabled and (Button = conf.Button) and
(Shift * conf.ShiftMask = conf.Shift) ) or (Shift * conf.ShiftMask = conf.Shift) ) or
( conf.Enabled2 and (Button = conf.Button2) and ( conf.Enabled2 and (Button = conf.Button2) and
(Shift * conf.ShiftMask2 = conf.Shift2) ); (Shift * conf.ShiftMask2 = conf.Shift2) );
ClickDone := Result; FClickDone := Result;
end; end;
begin begin
line := TSynEdit(SynEdit).PixelsToRowColumn(Point(X, Y)).Y; line := TSynEdit(SynEdit).PixelsToRowColumn(Point(X, Y)).Y;
FClickDone := False;;
FClickLine := line;
if line > SynEdit.Lines.Count then exit; if line > SynEdit.Lines.Count then exit;
ClickDone := False;;
case FFoldView.FoldType[FFoldView.TextIndexToScreenLine(Line-1)] of case FFoldView.FoldType[FFoldView.TextIndexToScreenLine(Line-1)] of
cfCollapsed : cfCollapsed :
@ -183,40 +183,55 @@ begin
FFoldView.FoldAtTextIndex(Line-1, -1, 0); FFoldView.FoldAtTextIndex(Line-1, -1, 0);
end; end;
end; end;
if (Button = mbRight) then begin end;
if not ClickDone then begin
FPopUp.Items.Clear; function TSynGutterCodeFolding.HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean;
c := FFoldView.OpenFoldCount(line-1); var
SetLength(FMenuInf,c); c, i: Integer;
for i := c-1 downto 0 do begin inf: TFoldViewNodeInfo;
inf := FFoldView.OpenFoldInfo(line-1, i); m: TMenuItem;
FMenuInf[i] := inf; s, s2: String;
if (i < c-1) and (FMenuInf[i+1].LineNum = line) and (inf.LineNum <> line) line: LongInt;
then begin begin
m := TMenuItem.Create(FPopUp); Result := inherited HasCustomPopupMenu(PopMenu);
m.Caption := cLineCaption; line := FClickLine;
m.Tag := -1; if line > SynEdit.Lines.Count then exit;
FPopUp.Items.Add(m);
end; if not FClickDone then begin
s := copy(inf.Text, 1, inf.HNode.LogXStart-1); FPopUp.Items.Clear;
if length(s) > 30 then s := copy(s,1,15) + '...' + copy(s, inf.HNode.LogXStart-11,10); c := FFoldView.OpenFoldCount(line-1);
s := s + copy(inf.Text, inf.HNode.LogXStart, 30 + (30 - length(s))); SetLength(FMenuInf,c);
s2 := ''; for i := c-1 downto 0 do begin
if inf.OpenCount > 1 then inf := FFoldView.OpenFoldInfo(line-1, i);
s2 := format(' (%d/%d)', [inf.ColIndex+1, inf.OpenCount]); FMenuInf[i] := inf;
if (i < c-1) and (FMenuInf[i+1].LineNum = line) and (inf.LineNum <> line)
then begin
m := TMenuItem.Create(FPopUp); m := TMenuItem.Create(FPopUp);
m.Caption := format('%4d %-12s %s', [ inf.LineNum, inf.Keyword+s2+':', s]); m.Caption := cLineCaption;
m.ShowAlwaysCheckable := true; m.Tag := -1;
m.Checked := inf.Folded;
m.Tag := i;
m.OnClick := {$IFDEF FPC}@{$ENDIF}PopClicked;
FPopUp.Items.Add(m); FPopUp.Items.Add(m);
end; end;
FPopUp.PopUp; s := copy(inf.Text, 1, inf.HNode.LogXStart-1);
if length(s) > 30 then s := copy(s,1,15) + '...' + copy(s, inf.HNode.LogXStart-11,10);
s := s + copy(inf.Text, inf.HNode.LogXStart, 30 + (30 - length(s)));
s2 := '';
if inf.OpenCount > 1 then
s2 := format(' (%d/%d)', [inf.ColIndex+1, inf.OpenCount]);
m := TMenuItem.Create(FPopUp);
m.Caption := format('%4d %-12s %s', [ inf.LineNum, inf.Keyword+s2+':', s]);
m.ShowAlwaysCheckable := true;
m.Checked := inf.Folded;
m.Tag := i;
m.OnClick := {$IFDEF FPC}@{$ENDIF}PopClicked;
FPopUp.Items.Add(m);
PopMenu := FPopUp;
end; end;
Result := True;
end; end;
end; end;
procedure TSynGutterCodeFolding.PopClicked(Sender: TObject); procedure TSynGutterCodeFolding.PopClicked(Sender: TObject);
var var
inf: TFoldViewNodeInfo; inf: TFoldViewNodeInfo;