unit SynPopupMenu; {$mode ObjFPC}{$H+} interface uses Classes, SysUtils, Menus, SynEdit, SynEditStrConst; type TSynDefaultPopupMenu = (dpmDisabled, dpmBefore, dpmAfter); TSynPopupMenu = class(TPopupMenu) private FDefaultPopupMenu: TSynDefaultPopupMenu; procedure FillDefaultMenu; procedure ClearDefaultMenu; protected procedure ItemOnClick(Sender: TObject); public constructor Create(AOwner: TComponent); override; procedure PopUp(X, Y: Integer); override; published property DefaultPopupMenu: TSynDefaultPopupMenu read FDefaultPopupMenu write FDefaultPopupMenu default dpmBefore; end; implementation type TMenuEntry = (meNone, meUndo, meRedo, meCut, meCopy, mePaste, meDelete, meSelectAll); { TSynPopupMenu } constructor TSynPopupMenu.Create(AOwner: TComponent); begin inherited; FDefaultPopupMenu := dpmBefore; end; procedure TSynPopupMenu.FillDefaultMenu; var i: Integer; procedure AddMenuItem(const ACaption: string; const ATag: TMenuEntry); var FItem: TMenuItem; begin FItem := TMenuItem.Create(Self); FItem.Caption := ACaption; FItem.OnClick := @ItemOnClick; FItem.Tag := Integer(ATag); if FDefaultPopupMenu = dpmAfter then Items.Add(FItem) else Items.Insert(i, FItem); Inc(i); end; var FEmpty: Boolean; begin if FDefaultPopupMenu = dpmDisabled then Exit; i := 0; FEmpty := Items.Count = 0; if not FEmpty and (FDefaultPopupMenu = dpmAfter) then // separator AddMenuItem('-', meNone); AddMenuItem(SYNS_Undo, meUndo); AddMenuItem(SYNS_Redo, meRedo); AddMenuItem('-', meNone); AddMenuItem(SYNS_Cut, meCut); AddMenuItem(SYNS_Copy, meCopy); AddMenuItem(SYNS_Paste, mePaste); AddMenuItem('-', meNone); AddMenuItem(SYNS_Delete, meDelete); AddMenuItem(SYNS_SelectAll, meSelectAll); if not FEmpty and (FDefaultPopupMenu = dpmBefore) then // separator AddMenuItem('-', meNone); end; procedure TSynPopupMenu.ClearDefaultMenu; var i: Integer; begin for i := Items.Count - 1 downto 0 do if Items[i].OnClick = @ItemOnClick then Items.Delete(i); end; procedure TSynPopupMenu.ItemOnClick(Sender: TObject); begin with TCustomSynEdit(PopupComponent) do case TMenuEntry(TMenuItem(Sender).Tag) of meUndo: Undo; meRedo: Redo; meCut: CutToClipboard; meCopy: CopyToClipboard; mePaste: PasteFromClipboard; meDelete: SelText := ''; meSelectAll: SelectAll; end; end; procedure TSynPopupMenu.PopUp(X, Y: Integer); var i: Integer; begin ClearDefaultMenu; if PopupComponent is TCustomSynEdit then begin FillDefaultMenu; for i := 0 to Items.Count - 1 do with TCustomSynEdit(PopupComponent) do if Items[i].OnClick = @ItemOnClick then // make sure it's ours case TMenuEntry(Items[i].Tag) of meUndo: Items[i].Enabled := CanUndo; meRedo: Items[i].Enabled := CanRedo; meCut: Items[i].Enabled := SelAvail and not ReadOnly; meCopy: Items[i].Enabled := SelAvail; mePaste: Items[i].Enabled := CanPaste; meDelete: Items[i].Enabled := SelAvail and not ReadOnly; meSelectAll: Items[i].Enabled := HasText([shtIncludeVirtual]); end; end; inherited; end; end.