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}
Windows,
{$ENDIF}
SysUtils, Classes, Messages, Controls, Graphics, Forms, StdCtrls, ExtCtrls,
SysUtils, Classes, Messages, Controls, Graphics, Forms, StdCtrls, ExtCtrls, Menus,
{$IFDEF SYN_MBCSSUPPORT}
Imm,
{$ENDIF}
@ -630,6 +630,7 @@ type
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
override;
function GetPopupMenu: TPopupMenu; override;
procedure NotifyHookedCommandHandlers(AfterProcessing: boolean;
var Command: TSynEditorCommand;
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);
end;
function TCustomSynEdit.GetPopupMenu: TPopupMenu;
begin
if (sfGutterClick in fStateFlags) and FGutter.HasCustomPopupMenu(Result) then
exit;
Result := inherited GetPopupMenu;
end;
procedure TCustomSynEdit.Paint;
var
rcClip, rcDraw: TRect;

View File

@ -5,7 +5,7 @@ unit SynGutter;
interface
uses
Classes, Controls, Graphics, LCLType, LCLIntf,
Classes, Controls, Graphics, LCLType, LCLIntf, Menus,
SynEditMarks, SynEditMiscClasses, SynEditMiscProcs, SynEditFoldedView,
SynTextDrawer, SynGutterBase, SynGutterLineNumber, SynGutterCodeFolding,
SynGutterMarks, SynGutterChanges;
@ -48,6 +48,7 @@ type
procedure Assign(Source: TPersistent); override;
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer);
function RealGutterWidth(CharWidth: integer): integer;
function HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MouseMove(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);
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);
begin
FMouseDownPart := PixelToPartIndex(X);

View File

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

View File

@ -34,6 +34,8 @@ type
TSynGutterCodeFolding = class(TSynGutterPartBase)
private
FClickDone: Boolean;
FClickLine: Integer;
FFoldView: TSynEditFoldedView;
FExpandedClickConf,
FCollapsedClickConf: TSynGutterFoldClickConfList;
@ -49,6 +51,7 @@ type
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: 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 MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure DoOnGutterClick(X, Y: integer); override;
@ -144,24 +147,21 @@ end;
procedure TSynGutterCodeFolding.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
var
ClickDone: Boolean;
m: TMenuItem;
line, i, c: Integer;
inf: TFoldViewNodeInfo;
s, s2: String;
line: Integer;
function isClick(conf : TSynGutterFoldClickConf): Boolean;
begin
if ClickDone then exit(False);
if FClickDone then exit(False);
Result := ( conf.Enabled and (Button = conf.Button) and
(Shift * conf.ShiftMask = conf.Shift) ) or
( conf.Enabled2 and (Button = conf.Button2) and
(Shift * conf.ShiftMask2 = conf.Shift2) );
ClickDone := Result;
FClickDone := Result;
end;
begin
line := TSynEdit(SynEdit).PixelsToRowColumn(Point(X, Y)).Y;
FClickDone := False;;
FClickLine := line;
if line > SynEdit.Lines.Count then exit;
ClickDone := False;;
case FFoldView.FoldType[FFoldView.TextIndexToScreenLine(Line-1)] of
cfCollapsed :
@ -183,40 +183,55 @@ begin
FFoldView.FoldAtTextIndex(Line-1, -1, 0);
end;
end;
if (Button = mbRight) then begin
if not ClickDone then begin
FPopUp.Items.Clear;
c := FFoldView.OpenFoldCount(line-1);
SetLength(FMenuInf,c);
for i := c-1 downto 0 do begin
inf := FFoldView.OpenFoldInfo(line-1, i);
FMenuInf[i] := inf;
if (i < c-1) and (FMenuInf[i+1].LineNum = line) and (inf.LineNum <> line)
then begin
m := TMenuItem.Create(FPopUp);
m.Caption := cLineCaption;
m.Tag := -1;
FPopUp.Items.Add(m);
end;
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]);
end;
function TSynGutterCodeFolding.HasCustomPopupMenu(out PopMenu: TPopupMenu): Boolean;
var
c, i: Integer;
inf: TFoldViewNodeInfo;
m: TMenuItem;
s, s2: String;
line: LongInt;
begin
Result := inherited HasCustomPopupMenu(PopMenu);
line := FClickLine;
if line > SynEdit.Lines.Count then exit;
if not FClickDone then begin
FPopUp.Items.Clear;
c := FFoldView.OpenFoldCount(line-1);
SetLength(FMenuInf,c);
for i := c-1 downto 0 do begin
inf := FFoldView.OpenFoldInfo(line-1, i);
FMenuInf[i] := inf;
if (i < c-1) and (FMenuInf[i+1].LineNum = line) and (inf.LineNum <> line)
then begin
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;
m.Caption := cLineCaption;
m.Tag := -1;
FPopUp.Items.Add(m);
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;
Result := True;
end;
end;
procedure TSynGutterCodeFolding.PopClicked(Sender: TObject);
var
inf: TFoldViewNodeInfo;